SlideShare una empresa de Scribd logo
1 de 203
Formation web
html5 / css3
Thierry GAYET - Thierry.Gayet@gmail.fr
TIMING DE LA FORMATION
Timing journalier :
●
Matin :
09h00-10h30 : première partie
10h30-10h45 : pause
10h45-13h00 : seconde partie
●
Pause déjeuner
●
Après-midi :
14h00-15h30 : troisième partie
15h30-15h45 : pause
15h45-17h00 : quatrième partie
●
Questions libres.
Timing journalier :
●
Matin :
09h00-10h30 : première partie
10h30-10h45 : pause
10h45-13h00 : seconde partie
●
Pause déjeuner
●
Après-midi :
14h00-15h30 : troisième partie
15h30-15h45 : pause
15h45-17h00 : quatrième partie
●
Questions libres.
merci de signaler toute contrainte de temps sur cette période dès le début
PLAN DE LA FORMATION

Historique du web & standards

Nouveaux éléments & attributs

Le formulaires web forms

Les microformats (microdata)

Audio & vidéo

Dessin avec canvas

Géolocalisation

Interraction avec les fichiers

Drap & drop

Push de données

Web messaging

Web sockets

Web storage

Web sql

Web workers

Application hors ligne

Exemples de CSS3

Jquery par l'exemple
Historique
4
Historique
5
Pour mieux comprendre la transition que le Web vit en ce moment, voici un bref historique de ce changement de cap.
→ 1998 : En prônant les avantages du XML, le W3C décide de ne plus continuer le développement du HTML (qui en
est à la version 4.01) et élabore une première spécification du XHTML (v 1.0). Cette version est un amalgame de la
syntaxe du HTML et des normes et standards XML.
Ce fut une bonne décision, car le XML étant strict sur ses normes, ça met de l’avant le souci d’un code bien structuré
et d’une uniformité entre les sites Web.
→ 2006 : 8 ans après cette décision, le W3C la remet en question et commence à penser que le XML (et le XHTML)
n’est peut être pas la voie du futur en conception Web. Il décide donc de travailler sur une nouvelle spécification du
HTML tout en continuant l’évolution du XHTML (v2.0). Plusieurs groupes (Mozilla, Opera, Google, …) viennent à
travailler conjointement avec le W3C sur le HTML 5.
Fait à noter : certains individus n’ont jamais arrêté de travailler sur le HTML depuis 1998. Pour en savoir plus sur la
période 1998-2006, vous pouvez lire sur le groupe WHATWG (www.whatwg.org).
→ 2009 : Le W3C arrête complètement de travailler sur le XHTML v2.0 et toutes les ressources sont redirigées vers
le HTML 5. La philosophie est désormais : pureté du design, par-dessus l’idéologie d’être rétro-compatible Adieu le
XHTML ! Les navigateurs restent compatibles avec le XHTML, mais l’emphase est maintenant sur l’implémentation
des spécifications du HTML 5.
Actuellement, il y a 2 spécifications du HTML 5 qui sont développées en parallèle :
● la version du WHATWG
● la version du W3C
Les deux groupes travaillent « relativement » conjointement, mais ils divergent sur certains points. Si vous devez
choisir une spécification, je vous conseille celle du W3C, qui est moins expérimentale.
Les spécifications du HTML 5 évoluent constamment. Ceci explique même pourquoi WHATWG a même décidé de
supprimer le « 5 » de HTML 5. Les navigateurs doivent donc toujours regarder les changements aux spécifications
pour se mettre à jour.
Historique
Quelques dates à retenir :
– 1991 HTML
– 1994 HTML 2
– 1996 CSS 1 + JavaScript
– 1997 HTML 4
– 1998 CSS 2
– 1999 HTML 4.01
– 2000 XHTML 1
– 2002 Tableless design
– 2004 WHATWG
– 2005 AJAX
– 2007 XHTML 2 boudé
– 2007 Le W3C récupère les travaux du WHATWG
– 2009 Arrêt des travaux sur XHTML 2
– 2010 HTML 5 + JavaScript API + CSS 3
6
HISTORIQUE
●
Liens :
– http://www.zdnet.fr/actualites/html5-petite-histoire-et-promesses-d
– http://www.weblife.fr/wp-content/uploads/2012/07/html5-histoire-
NOUVEAUX ELEMENTS
& ATTRIBUTS
8
HTML 5
● <!DOCTYPE html>
& <meta charset="UTF-8">
● Nouvelles balises
● Balises vidéos et audio
● Nouveaux champs de
formulaire
● Nouveaux attributs notamment
autofocus, placeholder
● Certaines balises et attributs
dépréciés : frame, frameset, big,
font, center, acronym, ...
● Intégration de SVG
● MicroData
● ...
LES NOUVEAUX ELEMENTS
→ Nouvelles balises :
● <section>
● <header>/<footer>
● <nav>
● <article>
● <aside>
● <hgroup>
● <time>
● <canvas>
● <audio>/<video>
● Et d’autres…
CSS 3
● Multi-colonnes
● Bordures
● Gradients
● Webfonts
● Manipulation de texte
● Animations & transitions
● Flexible box model
● Nouveaux selecteurs
● Media Queries
● ...
LES NOUVEAUX ELEMENTS
JavaScript
● Geolocation
● WebWorkers
● WebSockets
● Orientation
● Notification
● sessionStorage & localStorage
● Web SQL database & IndexedDB
● ...
LES NOUVEAUX ELEMENTS
HTML 5 + JavaScript
● Canvas 2D
● Intégration audio et vidéo
● Mode offline
● Gestion de l'historique
● Edition de contenu
● Drag & Drop
● Custom data attribute
● ...
LES NOUVEAUX ELEMENTS
CSS 3 + JavaScript
● Selectors
● Classlist
LES NOUVEAUX ELEMENTS
WebGL
● Avant Chrome 9, lancer chrome avec --enable-webgl
● Sous Firefox 4, about:config puis enable for all sites
● Exemple depuis Learning WebGL
● Body Browser de Google
LES NOUVEAUX ELEMENTS
A Venir
● Contacts API
● Webcam (Capture API)
● Device Orientation API
● Calendar API
● Speech input
● ...
LES NOUVEAUX ELEMENTS
LES FORMULAIRES
WEB FORMS
16
Nouveaux types d'entrées dans HTML5
Ce que nous connaissons aujourd'hui comme étant HTML5 Forms ou HTML5 Web Forms a démarré
sous le nom de Web Forms 2.0, une spécification pré-HTML5 créée par un groupe appelé WHATWG
(Web Hypertext Applications Technology Working Group).
La majeure partie du travail initial du WHATWG est devenue le point de départ ce que nous appelons
maintenant HTML5 et l'effort Web Forms 2.0 fait à présent partie de la spécification HTML5 officielle,
que vous pouvez consulter à l'adresse suivante : bit.ly/njrWvZ.
Une partie non négligeable de la spécification est consacrée à de nouveaux types et attributs de
contenu pour l'élément d'entrée, que vous trouverez à l'adresse suivante :
Comme je l'ai mentionné précédemment, la spécification introduit 13 nouveaux types d'entrées à
utiliser dans des formulaires : recherche, tél., url, e-mail, dateheure, date, mois, semaine, heure,
dateheure-locale, numéro, plage, couleur.
L'utilisation de ces nouveaux types est simple. Imaginons que je veuille insérer un nouveau champ
d'e-mail sur un formulaire de commande. Comme vous pouvez le voir sur la Figure 1, j'ai modifié la
page de commande du site Web de modèle Pâtisserie WebMatrix en lui ajoutant des champs, dont e-
mail.
LES WEBFORMS
La balise <input> en HTML4 possède les propriétés suivante :
Type Description
text A free-form text field, nominally free of line breaks.
password A free-form text field for sensitive information, nominally free of line breaks.
checkbox A set of zero or more values from a predefined list.
radio An enumerated value.
submit A free form of button initiates form submission.
file An arbitrary file with a MIME type and optionally a file name.
image A coordinate, relative to a particular image's size, with the extra semantic that it must be the
last value selected and initiates form submission.
hidden An arbitrary string that is not normally displayed to the user.
select An enumerated value, much like the radio type.
textarea A free-form text field, nominally with no line break restrictions.
button A free form of button which can initiates any event related to button.
Exemple de formulaire :
<form action="http://example.com/cgiscript.pl" method="post">
<p>
<label for="firstname">first name: </label>
<input type="text" id="firstname"><br />
<label for="lastname">last name: </label>
<input type="text" id="lastname"><br />
<label for="email">email: </label>
<input type="text" id="email"><br>
<input type="radio" name="sex" value="male"> Male<br>
<input type="radio" name="sex" value="female"> Female<br>
<input type="submit" value="send"> <input type="reset">
</p>
</form>
LES WEBFORMS
La balise <input> en HTML5 a évolué en incluant de nouvelles propriétés :
Type Description
datetime A date and time (year, month, day, hour, minute, second, fractions of a second) encoded
according to ISO 8601 with the time zone set to UTC.
datetime-local A date and time (year, month, day, hour, minute, second, fractions of a second) encoded
according to ISO 8601, with no time zone information.
date A date (year, month, day) encoded according to ISO 8601.
month A date consisting of a year and a month encoded according to ISO 8601.
week A date consisting of a year and a week number encoded according to ISO 8601.
time A time (hour, minute, seconds, fractional seconds) encoded according to ISO 8601.
number This accepts only numerical value. The step attribute specifies the precision, defaulting to 1.
range The range type is used for input fields that should contain a value from a range of numbers.
email This accepts only email value. This type is used for input fields that should contain an e-mail
address. If you try to submit a simple text, it forces to enter only email address in
email@eurogiciel.fr format.
url This accepts only URL value. This type is used for input fields that should contain a URL
address. If you try to submit a simple text, it forces to enter only URL address either in
http://www.eurogiciel.fr format or in http://example.com format.
Exemple de formulaire :
<form action="demo_form.asp" autocomplete="on">
First name:<input type="text" name="fname"><br>
Last name: <input type="text" name="lname"><br>
E-mail: <input type="email" name="email" autocomplete="off"><br>
<input type="submit">
</form>
LES WEBFORMS
Quelques exemples de formulaires :
<form>
<p><label>Customer name: <input></label></p>
<fieldset>
<legend> Pizza Size </legend>
<p><label> <input type=radio name=size> Small </label></p>
<p><label> <input type=radio name=size> Medium </label></p>
<p><label> <input type=radio name=size> Large </label></p>
</fieldset>
</form>
<form>
<p><label>Customer name: <input></label></p>
<fieldset>
<legend> Pizza Size </legend>
<p><label> <input type=radio name=size> Small </label></p>
<p><label> <input type=radio name=size> Medium </label></p>
<p><label> <input type=radio name=size> Large </label></p>
</fieldset>
<fieldset>
<legend> Pizza Toppings </legend>
<p><label> <input type=checkbox> Bacon </label></p>
<p><label> <input type=checkbox> Extra Cheese </label></p>
<p><label> <input type=checkbox> Onion </label></p>
<p><label> <input type=checkbox> Mushroom </label></p>
</fieldset>
</form>
LES WEBFORMS
<form>
<p><label>Customer name: <input></label></p>
<p><label>Telephone: <input type=tel></label></p>
<p><label>E-mail address: <input type=email></label></p>
<fieldset>
<legend> Pizza Size </legend>
<p><label> <input type=radio name=size> Small </label></p>
<p><label> <input type=radio name=size> Medium </label></p>
<p><label> <input type=radio name=size> Large </label></p>
</fieldset>
<fieldset>
<legend> Pizza Toppings </legend>
<p><label> <input type=checkbox> Bacon </label></p>
<p><label> <input type=checkbox> Extra Cheese </label></p>
<p><label> <input type=checkbox> Onion </label></p>
<p><label> <input type=checkbox> Mushroom </label></p>
</fieldset>
<p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900"></label></p>
<p><label>Delivery instructions: <textarea></textarea></label></p>
</form>
LES WEBFORMS
<form method="post"
enctype="application/x-www-form-urlencoded"
action="https://pizza.example.com/order.cgi">
<p><label>Customer name: <input name="custname"></label></p>
<p><label>Telephone: <input type=tel name="custtel"></label></p>
<p><label>E-mail address: <input type=email name="custemail"></label></p>
<fieldset>
<legend> Pizza Size </legend>
<p><label> <input type=radio name=size value="small"> Small </label></p>
<p><label> <input type=radio name=size value="medium"> Medium </label></p>
<p><label> <input type=radio name=size value="large"> Large </label></p>
</fieldset>
<fieldset>
<legend> Pizza Toppings </legend>
<p><label> <input type=checkbox name="topping" value="bacon"> Bacon </label></p>
<p><label> <input type=checkbox name="topping" value="cheese"> Extra Cheese </label></p>
<p><label> <input type=checkbox name="topping" value="onion"> Onion </label></p>
<p><label> <input type=checkbox name="topping" value="mushroom"> Mushroom </label></p>
</fieldset>
<p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900"
name="delivery"></label></p>
<p><label>Delivery instructions: <textarea name="comments"></textarea></label></p>
<p><button>Submit order</button></p>
</form>
LES WEBFORMS
<fieldset>
<legend>Display</legend>
<p><label><input type=radio name=c value=0 checked> Black on White</label>
<p><label><input type=radio name=c value=1> White on Black</label>
<p><label><input type=checkbox name=g> Use grayscale</label>
<p><label>Enhance contrast <input type=range name=e list=contrast min=0 max=100 value=0
step=1></label>
<datalist id=contrast>
<option label=Normal value=0>
<option label=Maximum value=100>
</datalist>
</fieldset>
<fieldset name="clubfields" disabled>
<legend> <label>
<input type=checkbox name=club onchange="form.clubfields.disabled = !checked">
Use Club Card
</label> </legend>
<p><label>Name on card: <input name=clubname required></label></p>
<p><label>Card number: <input name=clubnum required pattern="[-0-9]+"></label></p>
<p><label>Expiry date: <input name=clubexp type=month></label></p>
</fieldset>
LES WEBFORMS
<fieldset name="clubfields" disabled>
<legend> <label>
<input type=checkbox name=club onchange="form.clubfields.disabled = !checked">
Use Club Card
</label> </legend>
<p><label>Name on card: <input name=clubname required></label></p>
<fieldset name="numfields">
<legend> <label>
<input type=radio checked name=clubtype onchange="form.numfields.disabled = !checked">
My card has numbers on it
</label> </legend>
<p><label>Card number: <input name=clubnum required pattern="[-0-9]+"></label></p>
</fieldset>
<fieldset name="letfields" disabled>
<legend> <label>
<input type=radio name=clubtype onchange="form.letfields.disabled = !checked">
My card has letters on it
</label> </legend>
<p><label>Card code: <input name=clublet required pattern="[A-Za-z]+"></label></p>
</fieldset>
</fieldset>
LES WEBFORMS
LES WEBFORMS
●
Liens :
– http://diveintohtml5.info/forms.html
– http://msdn.microsoft.com/fr-fr/magazine/hh547102.aspx
– http://smashinghub.com/html5-web-forms-tutorials.htm
– http://miketaylr.com/code/input-type-attr.html
– http://miketaylr.com/code/html5-forms-ui-support.html
– http://miketaylr.com/code/html5-textarea-attribute-support.html
– http://www.whatwg.org/specs/web-apps/current-work/#the-textare
– http://www.w3schools.com/html/html5_form_attributes.asp
– http://www.standardista.com/html5/html5-web-forms/
– http://miketaylr.com/pres/html5/forms2.html
– http://estelle.github.io/forms/#slide1
LES MICROFORMATS
& MICRODATA
26
Le microformat propose une syntaxe qui s’apparente à du HTML classique et s’applique bien en
dehors de la norme HTML5 puisqu’il est compatible avec HTML4, ou XHTML1.0 par exemple. Il utilise
l’attribut class et certaines valeurs bien précises dans le but de “baliser” un contenu afin qu’il soit
interprété comme une donnée bien spécifique.
Voici un exemple de code un peu plus parlant :
<span class="hreview-aggregate">
<span class="item">
<span class="fn">Juiz Smart Mobile Admin</span>
</span>
<span class="rating">
Note de :
<span class="average">90</span> sur
<span class="best">100</span>
</span>
basée sur
<span class="count">35</span> votes.
</span>
Comme vous pouvez le constater, les microformats n’utilisent pas d’attribut ou de syntaxe trop
complexe, seulement des valeurs de classe bien précises.
Vous trouverez un bon nombre de données et d’outils sur le site microformats.org qui a proposé une
tentative de codification des pratiques courantes. Microformats.org a ainsi pu réunir un certain nombre
de “profils” XMPD que vous trouverez directement sur le wiki microformats. En plus de simples
valeurs de classe, microformat c’est également l’utilisation de l’attribut rel, c’est le format hCard, le
format hCalendar, etc...
LES MICROFORMATS
Les microdonnées :
Les microdonnées sont représentées par l’arrivée de nouveaux attributs en HTML5.
Il est alors possible de donner la référence du document utilisé pour baliser l’information directement
au sein de l’élément porteur de ces informations.
Il faut attirer l'attention sur l’arrivée d’un document qui tend à devenir une nouvelle référence pour
structurer des données : issu d’un consortium entre Google, Bing, Yahoo et Yandex, cette référence
est nommée schema.org. Ce sont d’ailleurs les schémas proposés par schema.org.
LES MICROFORMATS
Nouveaux attributs :
Il n’en existe pas énormément :
● itemscope : il permet de créer un item dont le type peut-être précisé grâce à l’attribut suivant,
● itemtype : couplé à itemscope, il accueille une URL vers la référence du schéma (ex :
“http://schema.org/Review”) qui devra respecter les valeurs de ce schéma,
● itemprop : il est porteur d’une valeur permettant de préciser la nature d’une donnée au sein d’un
schéma spécifié précédemment.
● itemref : il permet de faire le lien complémentaire entre deux données sans descendance.
● itemid : lorsque l’item possède une référence globale unique, comme par exemple un l’identifiant d’un
livre (urn:isbn:0-xxx-xxxxx-x). Il est attribué en même temps que l’attribut itemscope.
Ces attributs peuvent être transportés par n’importe quel élément (souvent des span pour injecter une
donnée sans mise en forme particulière), bien que certaines exceptions, évidentes, existent.
Exemple d’une simple revue :
<span itemscope itemtype="http://schema.org/Review">
<span itemprop="itemReviewed">Juiz Smart Mobile Admin</span>
<span itemprop="reviewRating">
Note de : 90 sur 100
</span>
basée sur 35 votes.
</span>
Rendu :
“Juiz Smart Mobile Admin Note de : 90 sur 100 basée sur 35 votes.”
LES MICROFORMATS
Exemple d’une notation imbriquée dans une revue :
Aussi appelée Embedded Items, l’imbrication de différents types de schéma peut intervenir dans le cas de
notre exemple de revue. En effet, notre exemple précédent manque quelque peu de précision, puisque
schema.org prévoit également un type de schéma pour les évaluations :
<div itemscope itemtype="http://schema.org/Review">
<h1 itemprop="itemReviewed">Juiz Smart Mobile Admin</h1>
<!-- Imbrication d’un item -->
<p itemprop="reviewRating" itemscope itemtype="http://schema.org/AggregateRating">
Note de :
<span itemprop="ratingValue">90</span> sur
<span itemprop="bestRating">100</span>
basée sur
<span itemprop="ratingCount">35</span> votes.
</p>
<!-- / fin de l’imbrication -->
<p itemprop="reviewBody">
Ce plugin proposé pour optimiser l'interface d'administration de[…]
</p>
</div>
Rendu :
“Juiz Smart Mobile Admin
Note de : 90 sur 100 basée sur 35 votes.
Ce plugin proposé pour optimiser l’interface d’administration de[…]”
LES MICROFORMATS
Création d’une fiche « film » :
Je prends volontairement ce dernier exemple pour vous présenter une technique qui permet d’associer des
informations sans qu’elles soient forcément imbriquées. En effet il arrive que la mise en page d’un site web
ou l’évolution de ses informations ne permette pas d’imbriquer les items comme nous l’avons vu juste
avant.
La fiche film est divisée en deux mais ses informations sont réunies sous le même item grâce à la propriété
itemref qui fait référence à l’élément aside#more-info à travers son identifiant “more-info”.
LES MICROFORMATS
Cet attribut permet de présenter un même item découpé en plusieur éléments à travers la page. Si les
informations de notre item Movie avaient été disséminées dans d’autres éléments de la page, il aurait été
possible de les cibler grâce à la valeur de leur attribut id de la sorte :
<article itemscope itemtype="http://schema.org/Movie" itemref="more-info id2 id3 id4">
Je ne vous ai pas encore expliqué la présence des éléments meta dans la page. Ceux-ci permettent
d’insérer une information qui a souvent besoin d’un formatage précis qui est peu intelligible par une
personne non aguerrie.
Prenons l’exemple de l’information “duration” qui représente la durée. Cette information doit être formatée
en respectant le format ISO 8601 qui définit un format de date ou de temps.
Dans notre fiche, il aurait été possible d’écrire :
<dd itemprop="duration">PT91M</dd>
Mais vous imaginez bien ici que PT91M est quelque peu dérangeant pour définir une durée d’une heure et
demi. C’est pourquoi, par convention – et si ce n’en est pas encore une il faudrait que ça le devienne –
l’information s’écrit dans un élément meta et à côté de l’information intelligible.
LES MICROFORMATS
Le code HTML correspondant à cette mise en page pourrait ressembler à cela :
<section role="main">
<article itemscope itemtype="http://schema.org/Movie" itemref="more-info">
<h1 itemprop="name">Nom du film de la fiche</h1>
<img itemprop="image" src="img/the-film.png" alt="" width="150" height="150">
<section itemprop="video" itemscope itemtype="http://schema.org/VideoObject">
<h2>Trailer : <span itemprop="name">Nom du film de la fiche</span></h2>
<meta itemprop="duration" content="T1M33S">
<meta itemprop="thumbnail" content="image-miniature-du-trailer.jpg">
<object …>
<param …>
<embed type="application/x-shockwave-flash" …>
</object>
<p itemprop="description">Courte description de la vidéo</p>
</section>
<section itemprop="description">
<p>Contenu principal de ma fiche film</p>
</section>
<footer>
<dl>
<dt>Réalisateur</dt>
<dd itemprop="director">Emily Atef</dd>
<dt>Acteurs</dt>
<dd itemprop="actors">Maria-Victoria Dragus</dd>
<dd itemprop="actors">Roeland Wiesnekker</dd>
<dd itemprop="actors">Wolfram Koch</dd>
LES MICROFORMATS
<dd itemprop="actors">Christine Citti</dd>
<dd itemprop="actors">Nathalie Boutefeu</dd>
<dt>Distributeur</dt>
<dd itemprop="provider">Les Films du Losange</dd>
<dt>Musique par</dt>
<dd itemprop="musicBy">John Smith</dd>
<dt>Ratio d'image</dt>
<dd>2.35</dd>
</dl>
</footer>
</article>
<aside id="more-info">
<dl>
<dt>Langues</dt>
<dd><meta itemprop="inLanguage" content="fr">Français</dd>
<dd><meta itemprop="inLanguage" content="de">Allemand</dd>
<dt>Année de production</dt>
<dd><time datetime="2011" itemprop="dateCreated">2011</time></dd>
<dt>Date de sortie</dt>
<dd><time datetime="2011-04-25" itemprop="datePublished">25 avril 2012</time></dd>
<dt>Genre</dt>
<dd itemprop="genre">Drame</dd>
<dt>Durée</dt>
<dd><meta itemprop="duration" content="PT91M">91 min</dd>
</dl>
</aside>
</section>
LES MICROFORMATS
LES MICROFORMATS
●
Liens :
– http://microformats.org/wiki/html5
– http://html5doctor.com/microformats/
– http://speckyboy.com/2011/01/24/beginners-study-guide-to-html5-
– http://www.alsacreations.com/tuto/lire/1224-microformats-html5-m
AUDIO & VIDEO
36
L'élément <video>, cousin de <audio> offre en HTML5 une solution simple, native pour les
navigateurs pour l'intégration d'une vidéo dans une page web. Elle permet également de proposer
une alternative à l'utilisation de Flash pour les plate-formes ne le supportant pas (iOS par exemple
avec iPhone, iPod, iPad...).
La syntaxe de base de la balise video est extrêmement simple :
<video controls src="video.ogv">Ici la description alternative</video>
L'attribut src définit bien entendu l'adresse du fichier vidéo, tout comme pour la balise img lorsqu'il
s'agit d'une image. Si vous indiquez les dimensions avec les attributs height et width, c'est encore
mieux, et si tout va bien, un élément devrait s'afficher dans le navigateur... pour peu que celui-ci
supporte le format de vidéo indiqué dans la source.
AUDIO & VIDEO
On peut également proposer plusieurs sources dans plusieurs formats différents en indiquant les
types MIME grâce à l'attribut type :
<video width="400" height="222" controls="controls">
<source src="video.mp4" type="video/mp4" />
<source src="video.webm" type="video/webm" />
<source src="video.ogv" type="video/ogg" />
Ici l'alternative à la vidéo : un lien de téléchargement, un message, etc.
</video>
Les navigateurs ne pouvant pas lire le MP4/H.264 ni la version WebM nativement (comme Firefox 3.6
par exemple) prendront la version au format Ogg Theora. Cela vous oblige néanmoins à encoder le
fichier avec différents codecs.
Particularité de la syntaxe XHTML : il faut ajouter controls="controls" (et pas juste controls comme
vous pourrez le voir sur le premier exemple) pour afficher les possibilités de contrôle de la vidéo. Ceci
est valable pour tous les attributs (autoplay, etc.).
AUDIO & VIDEO
● Attributs :
L'attribut controls donne accès aux contrôles de lecture (boutons de navigation, volume, etc, selon les
possibilités du navigateur), ou les masque s'il est omis.
L'attribut preload="auto" permet de de spécifier au navigateur de débuter le téléchargement de la
vidéo tout de suite, en anticipant sur le fait que l'utilisateur lira la vidéo. Attention, cette option est à
manier avec prudence (il est préférable que ce soit la seule raison d'être de la page). Note : il s'agit de
l'ancien attribut autobuffer qu'il vous faudra laisser pour Firefox 3.5 et 3.6.
L'attribut autoplay="true" comme son nom l'indique, permet de lancer la lecture automatiquement.
Cela peut également être problématique avec une connexion à faible bande passante ou sur un
terminal mobile. De manière générale, évitez d'imposer vos choix à l'utilisateur... et à sa connexion
internet.
L'attribut poster="image.jpg" permet d'indiquer une image à afficher par défaut dans l'espace réservé
par la vidéo, avant que la lecture de celle-ci ne soit lancée.
L'attribut loop indique que la lecture doit s'effectuer en boucle.
● Prérequis :
Pensez également à préciser les types MIME dans un fichier .htaccess pour être sûr qu'ils soient
corrects, les trois lignes suivantes suffisent à s'assurer la tranquilité :
AddType video/ogg .ogv
AddType video/mp4 .mp4
AddType video/webm .webm
AUDIO & VIDEO
● Formats :
Plusieurs formats tiennent le devant de la scène : WebM, MP4 et Ogg Theora. Même si le but de ce
tutoriel est de proposer une solution d'intégration de la balise video compatible sur le plus de
navigateurs possible (et pas de discuter du choix des formats dans un interminable débat), faisons
quand même une présentation rapide.
→ H.264/MP4 :
H.264 est supporté par le Moving Picture Experts Group. C'est un format non-libre (soumis à brevets)
et non-gratuit. Toutefois, il est gratuit dans certaines utilisations (la diffusion gratuite de vidéos par des
sites Web par exemple).
Les fichiers MP4 utilisant H.264 sont lisibles nativement sur les navigateurs Apple (Safari, Safari
Mobile) ainsi que sur Google Chrome.
AUDIO & VIDEO
→ OGG/Theora :
Theora est un format de compression vidéo open-source, sans brevets. Ceci donne le droit à tous
d'utiliser Theora (à des fins non commerciales tout comme à des fins commerciales) sans devoir
payer de redevance au consortium MPEG.
OGG/Theora est lisible sur Firefox, Opéra, et Google Chrome.
AUDIO & VIDEO
AUDIO & VIDEO
→ WebM/VP8 :
WebM est un format multimédia ouvert qui a été lancé par Google (après rachat de la société On2
Technologies). L'utilisation est en libre et gratuite.
Comme on peut le constater, il y a une grande disparité dans le support des codecs, chacun
défendant ses intérêts pour le meilleur ou pour le pire (commerciaux ou libres).
AUDIO & VIDEO
●
Liens :
– http://diveintohtml5.info/video.html
– http://fr.wikipedia.org/wiki/Theora
– http://www.videojs.com/
–
CANVAS
44
Introduit à l'origine par Apple pour être utilisé dans WebKit pour des logiciels comme Dashboard et le
navigateur Safari, canvas a été par la suite adopté par les navigateurs utilisant Gecko (notamment
Mozilla Firefox) et Opera, avant d'être standardisé par le groupe de travail WHATWG. Novell a
développé une extension activant les XForms dans Internet Explorer1 offrant ainsi une prise en
charge des fonctionnalités de canvas.
<canvas id="mon_canvas" width="350" height="350">
Texte alternatif pour les navigateurs ne supportant pas Canvas.
</canvas>
À partir de ce moment, tout se passe du côté de JavaScript, qui va se servir de cet élément HTML
pour accéder à la surface de dessin. Pour ceci, deux fonctions sont appelées :
getElementById() qui va permettre d'aller chercher et cibler l'élément <canvas> identifié par son
attribut id unique (ici mon_canvas),puis la méthode getContext() de l'élément ainsi récupéré pour
savoir dans quel contexte de dessin (2D ou 3D) le script va pouvoir agir, et de quelles fonctions il
pourra disposer. Le contexte sera l'élément central de gestion de Canvas.
<script type="text/javascript">
var c = document.getElementById("mon_canvas");
var ctx = c.getContext("2d");
// Dessine un rectangle rouge
ctx.fillStyle = 'red';
ctx.fillRect(30, 30, 50, 50);
</script>
Canvas
Tous les exemples suivants dans ce tutoriel feront appel à cette structure (élément Canvas +
élément script + appel à getElementById + getContext) qui ne sera pas reprécisée à chaque
fois.
Après cette étape préliminaire de mise en place, il faut se plonger dans l'ensemble des
méthodes de dessin 2D.
Celles-ci vont toutes exploiter le même système de coordonnées :
● Le point de référence (0,0) est situé en haut à gauche ;
● L'axe horizontal (x) est défini par la première coordonnée ;
● L'axe vertical (y) est défini par la seconde coordonnée ;
● Ces valeurs correspondent à la grille entourant les pixels, et non pas aux pixels eux-
mêmes.
Par exemple le point de coordonnées (4,2) sera situé 4 pixels à droite du coin supérieur
gauche, et 2 pixels en-dessous.
Canvas
Si l'on trace un polygone entre les 3 points présents sur ce schéma, on obtiendra un triangle.
Pour commencer, voici un exemple simple qui dessine deux rectangles ayant une intersection, l'un
d'entre-eux possédant une transparence alpha :
<html>
<head>
<script type="application/x-javascript">
function draw()
{
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect (10, 10, 55, 50);
ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
ctx.fillRect (30, 30, 55, 50);
}
</script>
</head>
<body onload="draw()">
<canvas id="canvas" width="300" height="300"></canvas>
</body>
</html>
La fonction draw récupère l'élément canvas, et ensuite son contexte 2d. L'objet ctx peut ensuite être
utilisé pour dessiner réellement vers le canevas. L'exemple remplit simplement les deux rectangles, en
positionnant fillStyle à deux couleurs différentes à l'aide des spécifications de couleur CSS et d'un appel à
fillRect. Le second appel à fillStyle utilise rgba() pour spécifier une valeur alpha parmi les informations de
couleur.
Les appels à fillRect, strokeRect et clearRect affichent un rectangle plein, surligné ou vide. Pour afficher
des formes plus complexes, on utilise des chemins.
Canvas
La fonction beginPath commence un nouveau chemin, et moveTo, lineTo, arcTo, arc et des méthodes
similaires sont utilisées pour ajouter des segments au chemin. Le chemin peut être fermé à l'aide de
closePath. Une fois que le chemin est créé, vous pouvez utiliser fill ou stroke pour afficher celui-ci sur le
canevas.
<html>
<head>
<script type="application/x-javascript">
function draw()
{
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
ctx.beginPath();
ctx.moveTo(30, 30);
ctx.lineTo(150, 150);
ctx.bezierCurveTo(60, 70, 60, 70, 70, 150);
ctx.lineTo(30, 30);
ctx.fill();
}
</script>
</head>
<body onload="draw()">
<canvas id="canvas" width="300" height="300"></canvas>
</body>
</html>
L'appel à fill() ou stroke() provoque l'utilisation du chemin. Pour être rempli ou dessiné à nouveau, le
chemin devra être recréé.
Canvas
Canvas
Canvas
●
Liens :
– http://www.html5canvastutorials.com/
– http://www.lafermeduweb.net/tutorial/l-element-html-5-canvas-p2
– http://en.wikipedia.org/wiki/Canvas_element
– http://www.w3schools.com/html/html5_canvas.asp
– http://www.whatwg.org/specs/web-apps/current-work/#dynamic
– https://developer.mozilla.org/fr/docs/Web/HTML/Canvas?redirect
– http://modern-carpentry.com/workshop/html5/waveform/
– http://www.crazyws.fr/dev/20-canvas-html5-pour-vous-inspirer-8I
Géolocalisation
51
Une des nouveautés introduites par HTML5 est la géolocalisation utilisable via une
API d'un navigateur.
Cela permet aux pages web d'interroger le navigateur sur la position géographique
de l'utilisateur.
L'API de base permet d'obtenir les coordonnées en latitude et en longitude ainsi
que l'altitude.
Celles-ci peuvent alors être exploitées par le biais d'une carte (de type Google
Map).
Détection du support :
if (navigator.geolocation)
{
//le navigateur supporte la géolocalisation
//suite du code ici
} else {
alert('Votre navigateur ne supporte pas la géolocalisation HTML5');
}
Géolocalisation
Détail de la méthode getCurrentPosition() :
PropertyProperty DescriptionDescription
coords.latitude The latitude as a decimal number
coords.longitude The longitude as a decimal number
coords.accuracy The accuracy of position
coords.altitude The altitude in meters above the mean sea level
coords.altitudeAccuracy The altitude accuracy of position
coords.heading The heading as degrees clockwise from North
coords.speed The speed in meters per second
timestamp The date/time of the response
Géolocalisation
Exemple de code pour un client :
<script>
var x = document.getElementById("demoLoc");
function getLocation()
{
if (navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(showPosition);
} else{
x.innerHTML="Geolocation is not supported by this browser.";}
}
function showPosition(position)
{
x.innerHTML="Latitude:"+position.coords.latitude + "<br>Longitude: " + position.coords.longitude;
}
</script>
Géolocalisation
Gestion des erreurs :
function showError(error)
{
switch(error.code)
{
case error.PERMISSION_DENIED:
x.innerHTML="User denied the request for Geolocation."
break;
case error.POSITION_UNAVAILABLE:
x.innerHTML="Location information is unavailable."
break;
case error.TIMEOUT:
x.innerHTML="The request to get user location timed out."
break;
case error.UNKNOWN_ERROR:
x.innerHTML="An unknown error occurred."
break;
}
}
Code d'erreurs :
● Permission denied : l'utilisateur n'est pas autorisé pour utiliser la géolocalisation
● Position unavailable : géolocalisation impossible
● Timeout : timeout pour aller jusqu'au bout de la géolocalisation
Géolocalisation
Example d'affichage de la position sur une carte :
function showPosition(position)
{
var latlon = position.coords.latitude+","+position.coords.longitude;
var img_url = "http://maps.googleapis.com/maps/api/staticmap?center="
+latlon+"&zoom=14&size=400x300&sensor=false";
document.getElementById("mapholder").innerHTML="<img src='" + img_url + "'>";
}
Géolocalisation
Autre méthodes :
● watchPosition() : retourne la position courante ainsi que le mouvement via une icône
(voiture).
● clearWatch() : arrête la méthode watchPosition
Example d'utilisation de la méthode watchPosition :
<script>
var x = document.getElementById("demo");
function getLocation()
{
if (navigator.geolocation)
{
navigator.geolocation.watchPosition(showPosition);
} else {
x.innerHTML="Geolocation is not supported by this browser.";
}
}
function showPosition(position)
{
x.innerHTML="Latitude: " + position.coords.latitude +
"<br>Longitude: " + position.coords.longitude;
}
</script>
Géolocalisation
Géolocalisation
●
Liens :
– http://www.w3schools.com/html/tryit.asp?filename=tryhtml5_geo
– http://dev.w3.org/geo/api/spec-source.html
– http://www.html5-css3.fr/html5/tutoriel-geolocalisation-html5
– http://debray-jerome.developpez.com/articles/l-api-geolocalisation
– http://html5demos.com/geo
– http://html5professor.com/tutoriels-6.html
–
Gérer les fichiers
59
L'API offerte aux navigateur web pour gérer les fichiers permet:
● De gérer une liste de fichiers (1:n) sélectionnable depuis la balise <input
type="file">
● Gestion de fichiers raw de type binaires avec autorisations d'accès d'une zone
d'octets
● Une interface détaillant le nom du(des) fichier(s), leur type et leur URL
● Une interface permettant de lire un fichier
● Une gestion d'exception permettant la gestion des exceptions
Gérer les fichiers
Vérifier le support disponible :
if (window.File && window.FileReader && window.FileList && window.Blob)
{
// Accès possible
} else {
alert('The File APIs are not fully supported in this browser.');
}
Création d'un handle sur un fichier :
// Récupère le path + nom du fichier
var file = document.forms['uploadData']['fileChooser'].files[0];
// Autre moyen de récupérer le path + nom du fichier
// var file = document.forms['uploadData']['fileChooser'].files.item(0);
if (file) // ou if (file != undefined)
{
// Traitements sur le fichier . . .
}
Gérer les fichiers
Soit le code HTML suivant :
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
Voici un exemple de code
gérant les fichiers :
<script>
function handleFileSelect(evt)
{
var files = evt.target.files;
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++)
{
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
'</li>');
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
Gérer les fichiers
Création d'un handle sur un fichier :
// Récupère le path + nom du fichier
var file = document.forms['uploadData']['fileChooser'].files[0];
// Autre moyen de récupérer le path + nom du fichier
// var file = document.forms['uploadData']['fileChooser'].files.item(0);
if (file) // ou if (file != undefined)
{
// Traitements sur le fichier . . .
}
Soit le code HTML suivant :
<div id="drop_zone">Drop files here</div>
<output id="list"></output>
Voici un exemple de code gérant les fichiers déposé en drag/drop :
<script>
function handleFileSelect(evt)
{
evt.stopPropagation();
evt.preventDefault();
var files = evt.dataTransfer.files;
var output = [];
for (var i = 0, f; f = files[i]; i++)
{
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
'</li>');
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
Gérer les fichiers
(...)
function handleDragOver(evt)
{
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}
// Setup the dnd listeners.
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
</script>
Gérer les fichiers
A aprtir du code html & css suivant :
<style>
.thumb
{
height: 75px;
border: 1px solid #000;
margin: 10px 5px 0 0;
}
</style>
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
Le code JS permettant de lire le fichier est le suivant :
<script>
function handleFileSelect(evt)
{
var files = evt.target.files; // FileList object
for (var i = 0, f; f = files[i]; i++)
{
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
Gérer les fichiers
(...)
reader.onload = (function(theFile)
{
return function(e)
{
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
Gérer les fichiers
A partir du code html suivant :
<style>
#byte_content
{
margin: 5px 0;
max-height: 100px;
overflow-y: auto;
overflow-x: hidden;
}
#byte_range { margin-top: 5px; }
</style>
<input type="file" id="files" name="file" /> Read bytes:
<span class="readBytesButtons">
<button data-startbyte="0" data-endbyte="4">1-5</button>
<button data-startbyte="5" data-endbyte="14">6-15</button>
<button data-startbyte="6" data-endbyte="7">7-8</button>
<button>entire file</button>
</span>
<div id="byte_range"></div>
<div id="byte_content"></div>
Gérer les fichiers
Le code Javascript permettant de télécharger un fichier binaire est le suivant :
<script>
function readBlob(opt_startByte, opt_stopByte)
{
var files = document.getElementById('files').files;
if (!files.length)
{
alert('Please select a file!');
return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
reader.onloadend = function(evt)
{
if (evt.target.readyState == FileReader.DONE)
{ // DONE == 2
document.getElementById('byte_content').textContent = evt.target.result;
document.getElementById('byte_range').textContent =
['Read bytes: ', start + 1, ' - ', stop + 1,
' of ', file.size, ' byte file'].join('');
}
};
var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
}
Gérer les fichiers
(...)
document.querySelector('.readBytesButtons').addEventListener('click', function(evt)
{
if (evt.target.tagName.toLowerCase() == 'button')
{
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);
</script>
Gérer les fichiers
A partir du code html suivant :
<style>
#progress_bar
{
margin: 10px 0;
padding: 3px;
border: 1px solid #000;
font-size: 14px;
clear: both;
opacity: 0;
-moz-transition: opacity 1s linear;
-o-transition: opacity 1s linear;
-webkit-transition: opacity 1s linear;
}
#progress_bar.loading
{
opacity: 1.0;
}
#progress_bar .percent
{
background-color: #99ccff;
height: auto;
width: 0;
}
</style>
Gérer les fichiers
<input type="file" id="files" name="file" />
<button onclick="abortRead();">Cancel read</button>
<div id="progress_bar"><div class="percent">0%</div></div>
Le code Javascript permettant de monitorer la progression de la lecture d'un fichier est le
suivant :
<script>
var reader;
var progress = document.querySelector('.percent');
function abortRead()
{
reader.abort();
}
function errorHandler(evt)
{
switch(evt.target.error.code) {
case evt.target.error.NOT_FOUND_ERR:
alert('File Not Found!');
break;
case evt.target.error.NOT_READABLE_ERR:
alert('File is not readable');
break;
case evt.target.error.ABORT_ERR:
break; // noop
default:
alert('An error occurred reading this file.');
};
}
Gérer les fichiers
(...)
function updateProgress(evt)
{
// evt is an ProgressEvent.
if (evt.lengthComputable)
{
var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
// Increase the progress bar length.
if (percentLoaded < 100)
{
progress.style.width = percentLoaded + '%';
progress.textContent = percentLoaded + '%';
}
}
}
function handleFileSelect(evt)
{
// Reset progress indicator on new file selection.
progress.style.width = '0%';
progress.textContent = '0%';
reader = new FileReader();
reader.onerror = errorHandler;
reader.onprogress = updateProgress;
reader.onabort = function(e)
{
alert('File read cancelled');
};
reader.onloadstart = function(e)
{
document.getElementById('progress_bar').className = 'loading';
};
Gérer les fichiers
(...)
reader.onload = function(e)
{
// Ensure that the progress bar displays 100% at the end.
progress.style.width = '100%';
progress.textContent = '100%';
setTimeout("document.getElementById('progress_bar').className='';", 2000);
}
// Read in the image file as a binary string.
reader.readAsBinaryString(evt.target.files[0]);
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
Gérer les fichiers
Autre exemple :
var file = document.getElementById('file').files[0];
if (file)
{
// create an identical copy of file
// the two calls below are equivalent
var fileClone = file.slice();
var fileClone2 = file.slice(0, file.size);
var fileChunkFromEnd = file.slice(-(Math.round(file.size/2)));
var fileChunkFromStart = file.slice(0, Math.round(file.size/2));
// slice file from beginning till 150 bytes before end
var fileNoMetadata = file.slice(0, -150, "application/experimental");
}
Gérer les fichiers
Création d'un objet blob (Binary Large Object) :
var a = new Blob();
// Creation d'un tableau de 10.24 octets
var buffer = new ArrayBuffer(1024);
var shorts = new Uint16Array(buffer, 512, 128);
var bytes = new Uint8Array(buffer, shorts.byteOffset + shorts.byteLength);
var b = new Blob([toNativeLineEndings("foobarbazetcetc" + "birdiebirdieboo")], {type:
"text/plain;charset=UTF-8"});
var c = new Blob([b, shorts]);
var a = new Blob([b, c, bytes]);
var d = new Blob([buffer, b, c, bytes]);
Gérer les fichiers
Gérer les fichiers
●
Liens :
– http://www.html5rocks.com/en/tutorials/file/dndfiles/
– http://en.wikipedia.org/wiki/File_select
– http://www.html5rocks.com/en/tutorials/file/filesystem/?redirect_f
– http://dailyjs.com/2009/11/30/html5-file-api/
– http://dret.typepad.com/dretblog/2010/04/html5-file-writer-api.htm
– https://developer.mozilla.org/en-US/docs/Using_files_from_web_a
– http://dev.w3.org/2006/webapi/FileAPI/
– http://www.filosophy.org/post/27/a_state_of_limbo_the_html5_fil
Drag & drop
77
Créer un élément pouvant être déplacé :
Pour rendre un élément déplaçable, il suffit de lui ajouter l'attribut «draggable » à
true:
<img id="drag1" src="img_logo.gif" draggable="true"
ondragstart="drag(event)" width="336" height="69">
L'attribut draggable positionné à True permet donc d'activer le drag & drop vis à vis
de l'image avec l'id « drag1 ».
Drag & drop
Créer un élément conteneur pouvant reçevoir un élément à déplacer:
Pour définir un conteneur, il faut définir 2 callbacks sur les évènements ondrop et
ondragover :
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
Il faudra définir dans le HEAD de la page un style pour le div :
<style type="text/css">
#div1 { width:350px;height:70px;padding:10px;border:1px solid #aaaaaa; }
</style>
Les dimensions sont compatible avec les dimensions de l'image pouvant être déplacer
dans le div.
Drag & drop
Exemple d'implémentation des callbacks de gestion des évenements ondrop et
ondragover :
<script>
function allowDrop(ev)
{
ev.preventDefault();
}
function drag(ev)
{
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev)
{
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
</script>
Drag & drop
Drag & drop
●
Liens :
– http://html5demos.com/drag
– http://html5demo.braincracking.org/demo/dragNDrop.php
– http://www.startyourdev.com/codes/code-drag-drop.php
– http://chez-syl.fr/2012/03/drag-and-drop-html5-jquery/
– http://www.html5rocks.com/en/tutorials/dnd/basics/
Push de données
82
Une des raisons pour lesquels les SSE ont été maintenus dans l'ombre, c'est que
des API comme les Web Sockets fournissaient déjà un protocole riche et bi-
directionnel en duplex intégral.
Avoir un canal bidirectionnel est plus attrayant pour des choses comme des jeux,
des applications de messagerie, et pour le cas où vous avez besoin à proximité de
mises à jour en temps réel dans les deux sens.
Toutefois, dans certains scénarios de données n'a pas besoin d'être envoyé par le
client. Vous devez simplement mises à jour de certaines mesures du serveur.
Quelques exemples seraient état des mises à jour amis, cours de la Bourse, les fils​​
de nouvelles, ou d'autres mécanismes d'incitation automatisée de données (par
exemple, mettre à jour une base de données SQL Web côté client ou un magasin
d'objets IndexedDB).
Si vous avez besoin d'envoyer des données à un serveur, l'objet XMLHttpRequest
est utile.
Push server
PUSH
mono-directionnel
Les SSE sont envoyés via du HTTP1.1 traditionnel.
Cela signifie qu'ils n'ont pas besoin d'un protocole spécifique ou la mise en œuvre
de serveur pour obtenir de travail.
Les Web Sockets d'autre part, nécessitent des connexions en duplex intégral et des
serveurs de sockets Web dédiés pour gérer ce protocole.
En outre, les Server-Sent Events ont une variété de caractéristiques qui manque
aux Web sockets tel que :
● la reconnexion automatique ;
● les événements associés à un ID ;
● la possibilité d'envoyer des événements arbitraires
Push server
Exemple d'enregistrement sur un flux d'évènements serveur :
Cela revient à instancier un objet EventSource avec l'url du flux :
if (!!window.EventSource)
{
var source = new EventSource('stream.php');
} else {
// Result to xhr polling
}
Push server
Ensuite, il faut déclarer un handle de message pour chaque événement :
source.addEventListener('message', function(e)
{
console.log(e.data);
}, false);
source.addEventListener('open', function(e)
{
// Connection was opened.
}, false);
source.addEventListener('error', function(e)
{
if (e.readyState == EventSource.CLOSED)
{
// Connection was closed.
}
}, false);
Push server
Il est possible que le serveur envoie des données complexes sous format json :
data: {n
data: "msg": "hello world",n
data: "id": 12345n
data: }nn
Pour ce faire, un handle de message sera rajouté et le message sera parsé pour
reformer l'objet au format de type json :
source.addEventListener('message', function(e)
{
var data = JSON.parse(e.data);
console.log(data.id, data.msg);
}, false);
Le JSON (JavaScript Object Notation) peut et doit être vu comme une structure de
Données, ou le résultat d'une sérialiation d'objet.
Push server
Pour des messages plus complexes :
data: {"msg": "First message"}nn
event: userlogonn
data: {"username": "John123"}nn
event: updaten
data: {"username": "John123", "emotion": "happy"}nn
Le traitement sera le suivant :
source.addEventListener('message', function(e)
{
var data = JSON.parse(e.data);
console.log(data.msg);
}, false);
source.addEventListener('userlogon', function(e)
{
var data = JSON.parse(e.data);
console.log('User login:' + data.username);
}, false);
source.addEventListener('update', function(e)
{
var data = JSON.parse(e.data);
console.log(data.username + ' is now ' + data.emotion);
}, false);
Push server
Coté serveur une implémentation en PHP est la suivante :
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); // recommended to prevent caching of event data.
/**
* Constructs the SSE data format and flushes that data to the client.
*
* @param string $id Timestamp/id of this connection.
* @param string $msg Line of text that should be transmitted.
*/
function sendMsg($id, $msg)
{
echo "id: $id" . PHP_EOL;
echo "data: $msg" . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
$serverTime = time();
sendMsg($serverTime, 'server time: ' . date("h:i:s", time()));
?>
Push server
Autre implémentation en Node.js :
var http = require('http');
var sys = require('sys');
var fs = require('fs');
http.createServer(function(req, res)
{
//debugHeaders(req);
if (req.headers.accept && req.headers.accept == 'text/event-stream')
{
if (req.url == '/events')
{
sendSSE(req, res);
} else {
res.writeHead(404);
res.end();
}
} else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(fs.readFileSync(__dirname + '/sse-node.html'));
res.end();
}
}).listen(8000);
Push server
function sendSSE(req, res)
{
res.writeHead(200,
{
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
var id = (new Date()).toLocaleTimeString();
// Sends a SSE every 5 seconds on a single connection.
setInterval(function()
{
constructSSE(res, id, (new Date()).toLocaleTimeString());
}, 5000);
constructSSE(res, id, (new Date()).toLocaleTimeString());
}
Push server
Le fichier sse-node.html aura le contenu suivant :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<script>
var source = new EventSource('/events');
source.onmessage = function(e)
{
document.body.innerHTML += e.data + '<br>';
};
</script>
</body>
</html>
Push server
Web socket (WS) vs évènements (SSE pour Server-Sent Events) envoyé depuis le serveur :
Advantages de SSE opposé aux Web sockets:
● Tranport via http au lieu d'un protocole dédié ;
● Peut être quand même utilisé via un backport sur des navigateurs ne disposant pas du
support ;
● Support intégré incluant des re-connexions et event-id
● Portocol simple
Advantages des Web sockets opposé aux SSE :
● Communication temps réelle et bi-directionnelle
● Support natif de plusieurs navigateur web
Utilisation idéale des SSE :
● Alimentation de données en continue ;
● Mise à jour des données twitter, fb, chat, … ;
● Notification serveur->browser
Push server
SSE WEB SOCKETS
Push server
●
Liens :
– http://fr.wikipedia.org/wiki/Server_push
– http://html5hacks.com/blog/2013/04/21/push-notifications-to-the-b
– http://pusher.com/tutorials/html5_realtime_push_notifications
– http://www.w3schools.com/html/html5_serversentevents.asp
– http://html5-realtime-push-notifications.eu01.aws.af.cm/examples/
– https://github.com/pusher/html5-realtime-push-notifications
– http://boedesign.com/blog/2009/07/11/growl-for-jquery-gritter/
– https://github.com/ehynds/jquery-notify
– http://www.erichynds.com/blog/a-jquery-ui-growl-ubuntu-notifica
– http://www.erichynds.com/examples/jquery-notify/index.htm
– http://dev.w3.org/html5/eventsource/
Web messaging
95
96
Web messaging
Architecture :
Html5 page
Iframe XXX
(message)
Soit une page web contenant une iframe, on récupère son handle de la façon
suivante :
var o = document.getElementsByTagName('iframe')[0];
Ensuite on peut lui envoyer un message :
o.contentWindow.postMessage('Hello world',
'http://b.example.org/');
Web messaging
Web messaging
L'iframe pourra traiter le message via la callback suivante :
window.addEventListener('message', receiver, false);
function receiver(e)
{
if (e.origin == 'http://example.com')
{
if (e.data == 'Hello world')
{
e.source.postMessage('Hello', e.origin);
} else {
console.log(e.data);
}
}
}
Web messaging
●
Liens :
– http://www.w3.org/TR/webmessaging/
– http://en.wikipedia.org/wiki/Web_Messaging
– http://dev.opera.com/articles/view/window-postmessage-messagec
– http://msdn.microsoft.com/fr-fr/library/ie/hh781494(v=vs.85).aspx
– http://fr.slideshare.net/miketaylr/html5-web-messaging-7970364
– http://fr.slideshare.net/miketaylr/html5-web-messaging-7970364
–
Web sockets
100
Web sockets
●
Architecture :
101
Connexion persistante
serveurclient database
La connexion client/serveur :
- permet une communication « temps réel » pour des applications genre chat,
cours de bourse, … ;
- permet aux serveurs d'envoyer des évènements ;
- ouvert à l'initiative du client et reste ouvert par la suite ;
- le serveur doit supporter un certain nombre de sockets (1 par client)
data
Web sockets
→ Exemple d'application pour un mini-chat :
db users
Web sockets
http://bloga.jp/ws/jq/js/jquery.ws-0.3-noenc-pre.js
<script src="./jquery-1.3.2.min.js"></script>
<script src="./jquery.ws-0.3pre.js"></script>
<input id="msg" type="text" value="">
<button id="send">send</button>
<div id="board"></div>
<script type="text/javascript">
var wsoj = $.ws.conn(
{
url : "ws://example.com/mytest",
onopen    : function(e)
{
$("#board").prepend("conected");
},
onmessage : function(msg,wsoj)
{
$("#board").prepend(msg)
},
onclose   : function(e)
{
$("#board").prepend("closed");
}
});
$("#send").click(function()
{
$(wsoj).wssend($("#msg").val())
});
</script>
→ Exemple d'implémentation d'un client :
Web sockets
●
Langages pour le serveur :
– Java (ex : jWebsocket, … )
– PHP (ex : phpwebsocket, spoutserver… )
– Ruby
– Python (ex : pywebsocket, … )
– C# (ex : Nugget)
– Javascript (ex : node.js, … )
104
Web sockets
→ Exemple de serveur :
from mod_pywebsocket import msgutil
import thread
import getopt
import os
import sys
import time
_GOODBYE_MESSAGE = 'Goodbye'
file = '/somewhere/test'
class tail():
last_mtime = None
def __init__(self, filename, delay, sock):
self.filename = filename
self.delay = delay
self.sock = sock
def run(self):
while True:
time.sleep(self.delay)
stat = os.stat(self.filename)
if stat.st_mtime != self.last_mtime:
self.last_mtime = stat.st_mtime
self.read()
def read(self):
try:
length = 0
f = open(self.filename, 'r')
for line in f:
length += 1
f.seek(0)
cnt = 0
for line in f:
cnt += 1
if cnt == length:
msgutil.send_message(self.sock, line[:-1])
f.close
except Exception:
if(f):
f.close
def web_socket_do_extra_handshake(request):
pass # Always accept.
def web_socket_transfer_data(request):
attr = ()
thread.start_new_thread(tail(file, 0.5, request).run, attr)
while True:
try:
line = msgutil.receive_message(request)
f = open(file, 'a')
f.write(line+"")
os.fsync(f.fileno())
f.flush()
f.close
if line == _GOODBYE_MESSAGE:
Return
except Exception:
return
Web sockets
(suite)
Nécessite le module python : http://code.google.com/p/pywebsocket/
Web sockets
●
Liens :
– http://fr.wikipedia.org/wiki/Websocket
– http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-06
– http://svn.whatwg.org/webapps/complete.html#websocket
– http://www.ape-project.org/
– https://github.com/disconnect/apache-websocket
– http://jwebsocket.org/
– http://code.google.com/p/pywebsocket/
– http://blog.kaazing.com/2010/02/17/html5-web-sockets-and-pipeli
– http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-68
– http://archive.plugins.jquery.com/project/ws
– http://martinsikora.com/nodejs-and-websocket-simple-chat-tutoria
– http://dev.w3.org/html5/websockets/
Web storage
108
Web storage
Cookies limités à quelques ko contre quelques Mo pour les storages
Ajout de deux interfaces/objets de stockage :
→ Stockage de session sessionStorage :
L'interface sessionStorage mémorise les données sur la durée d'une session de
navigation, et sa portée est limitée à la fenêtre ou l'onglet actif.
Lors de sa fermeture, les données sont effacées. Contrairement au cookies,
il n'y a pas d'interférence. Chaque stockage de session est limité à un domaine
→ Stockage local localStorage :
L'interface localStorage mémorise les données sans limite de durée de vie.
Contrairement à sessionStorage, elles ne sont pas effacées lors de la fermeture
d'un onglet ou du navigateur. La portée de localStorage est de facto plus large :
il est possible de l'exploiter à travers plusieurs onglets ouverts pour le même
domaine ou plusieurs fenêtres ; à partir du moment où il s'agit bien sûr du même
Navigateur.
Il n'y a pas de partage des données Web Storage entre les différents navigateurs qui
peuvent être installés sur une même machine.
Web storage
Usages et précautions
Le stockage de données dans le navigateur web se prête à différentes applications,
particulièrement lorsqu'il s'agit d'exécuter des traitements sans faire intervenir le serveur,
ou lorsqu'il faut mémoriser facilement de petites quantités de données pour l'utilisateur
pour les faire persister durant sa navigation. Parmi ces avantages :
● stocker rapidement des données en cache sans faire intervenir le serveur (par
exemple via AJAX),
● augmenter la performance ressentie et faciliter les développements,
● se passer des cookies et du trafic HTTP supplémentaire qu'ils représentent (un cookie
est envoyé à chaque requête effectuée sur un domaine),
● exploiter un espace alloué plus important que la limite imposée par les cookies (fixée à
4 Ko),
● retrouver des données immédiatement à la reconnexion ou les mémoriser pour éviter
la perte s'il y a déconnexion.
Attention : les données ne sont pas cryptées, accessibles facilement à tout utilisateur ayant accès au navigateur, et modifiables de la
même façon. Il ne faut donc pas y placer d'informations sensibles.
Pour ces raisons et d'autres, certains navigateurs exigent de consulter la page appelant le stockage via un domaine, (c'est-à-dire avec
une url en http://, que ce soit localhost ou bien un nom de domaine complet) et non pas en fichier local (adresse file://). Sinon, une
exception de sécurité peut être déclenchée. Ceci peut sembler logique car les données sont en théorie attachées à un domaine.
Web storage
Hormis les spécificités concernant la persistance des données, les méthodes d'accès sont communes :
● setItem(clé,valeur) : stocke une paire clé/valeur
● getItem(clé) : retourne la valeur associée à une clé
● removeItem(clé) : supprime la paire clé/valeur en indiquant le nom de la clé
● key(index): retourne la clé stockée à l'index spécifié
● clear(): efface toutes les paires
Pour agrémenter le tout, la propriété .length renvoie le nombre de paires stockées.
La console Javascript des navigateurs est un outil essentiel pour tester et vérifier le bon fonctionnement de Web Storage.
Accès aux données :
Note : Les exemples suivants se basent sur sessionStorage mais fonctionneront de la même façon avec localStorage.
Web storage
Stockage :
sessionStorage.setItem("couleur","vert")
Le premier argument de setItem est la clé (toujours de type String). Elle précise
l'endroit où sont stockées les données afin de pouvoir les y retrouver ultérieurement.
Récupération :
var couleur = sessionStorage.getItem("couleur");
Grâce à la clé initialement créée avec setItem il est possible de récupérer facilement
les données. Ces dernières sont renvoyées sous la forme d'une chaîne de caractère.
Suppression :
sessionStorage.removeItem("couleur");
Nous supprimons l'élément de session "couleur".
Suppression totale :
sessionStorage.clear();
Suppression complète de toutes les valeurs de session.
Accès direct :
Dans la plupart des situations, les variables seront accessibles directement en tant
que membres de l'interface.
sessionStorage.couleur = "vert";
console.log(sessionStorage.couleur);
Web storage
Opera :
Chrome :
IE :
Web storage
Une première application peut être la mémorisation de champs de formulaire, pour stocker les données
entrées par l'utilisateur. Bien que ceci soit applicable à toute variable manipulée en JavaScript.
Pour ceci, l'événement change sur <textarea> est sollicité pour stocker la valeur courante de l'élément
dans sessionStorage.message :
<textarea id="message" name="message"
onchange="sessionStorage.message=this.value"></textarea>
Notez que cette façon de faire est très compacte mais n'est pas des plus
esthétiques car le code JavaScript se retrouve "mélangé" au contenu HTML de la
page.
Ce script doit être placé en fin de document :
<script>
// Détection du support du storage
if(typeof sessionStorage!='undefined')
{
// Vérifie si la variable message a été stoquée dans les sessionStorage :
if('message' in sessionStorage)
{
$('textarea#message').text() = sessionStorage.getItem('message');
}
} else {
console.log("sessionStorage n'est pas supporté");
}
</script>
http://www.codegateway.com/2012/03/get-textarea-value-in-jquery.html
Exemple n° 1 :
Un deuxième exemple très simple à mettre en place est celui d'un compteur de visites.
<p>Vous avez vu cette page <span id="visites"></span> fois</p>
Le principe est :
● aller interroger la clé visites dans localStorage dès le chargement du document
● effectuer toutes les vérifications nécessaires (est-ce qu'il y a déjà quelque chose stocké à cet
emplacement, peut-on convertir cette chaîne de texte en nombre entier)
● incrémenter le compteur
● le stocker à nouveau au même emplacement pour le conserver
● afficher la valeur à un emplacement dans la page
<script>
if(typeof localStorage!='undefined') {
// Récupération de la valeur dans web storage
var nbvisites = localStorage.getItem('visites');
// Vérification de la présence du compteur
if(nbvisites!=null) {
// Si oui, on convertit en nombre entier la chaîne de texte qui fut stockée
nbvisites = parseInt(nbvisites);
} else {
nbvisites = 1;
}
// Incrémentation
nbvisites++;
Exemple n° 2 :
Web storage
// Stockage à nouveau en attendant la prochaine visite...
localStorage.setItem('visites',nbvisites);
// Affichage dans la page
document.getElementById('visites').innerHTML = nbvisites;
} else {
alert("localStorage n'est pas supporté");
}
</script>
Pour l'affichage, cet exemple se sert de l'identifiant id et de la fonction getElementById() pour le cibler, afin
d'accéder à sa propriété innerHTML, c'est-à-dire son contenu HTML interne, modifiable.
Attention : cette information restera spécifique et locale au visiteur, ne sera pas échangée avec le serveur
(hors utilisation d'Ajax par exemple), et donc ne pourra être exploitée pour établir des statistiques
générales.
Web storage
Web storage
Utilisation de JSON :
Web Storage est bien pratique pour stocker de simples chaînes de texte. Lorsqu'il s'agit de manipuler des données
plus complexes, entre autres des objets JavaScript, il faut leslinéariser au préalable en chaînes de texte puisque
Web Storage n'accepte que ce type de données.
Le format JSON (JavaScript Object Notation) est la solution de prédilection. Deux méthodes équipent les
navigateurs modernes : JSON.stringify() qui prend en paramètre un objet et renvoie une chaîne de texte linéarisée,
et son inverse JSON.parse() qui reforme un objet à partir de la chaîne linéarisée.
Des frameworks populaires tels que jQuery sont équipés de fonctions similaires (parseJSON) pour les anciens
navigateurs qui ne seraient pas équipés en natifs de telles méthodes de conversion.
Stockage :
var monobjet =
{
propriete1 : "valeur1",
propriete2 : "valeur2"
};
var monobjet_json = JSON.stringify(monobjet);
sessionStorage.setItem("objet",monobjet_json);
Lecture :
var monobjet_json = sessionStorage.getItem("objet");
var monobjet = JSON.parse(monobjet_json);
// Affichage dans la console
console.log(monobjet);
Dans le cadre de la lisibilité de cette démonstration, cet exemple de code ne fait
appel que modestement à JSON, il serait possible de l'exploiter de façon beaucoup
plus complexe et évoluée en fonction de la quantité de données à stocker et de leur
provenance.
Aller plus loin :
L'API prévoit aussi des événements storage pour être notifié à chaque changement opéré dans l'espace
alloué. Ceux-ci ne sont pas encore très répandus.
Pour mettre en place des stockages plus évolués, pour des données binaires ou bien du point de vue de la
structure et des opérations de recherche, tri et maintenance, deux approches coexistent :
WebSQL dont la spécification est au point mort et qui ne sera pas maintenu à long terme ni intégré à
Firefox et Internet Explorer, mais qui a été implémenté par WebKit et Opera. Cette tentative faisait entrer le
langage SQL côté client, ce qui était compréhensible pour les développeurs utilisant déjà les bases côté
serveur (MySQL, etc) mais n'est pas conforme à l'esprit des différents standards du web : cela nécessiterait
de spécifier totalement SQL ou un sous-ensemble tel que SQLite ce qui n'est pas le rôle du W3C.
IndexedDB (Indexed Database) revêt une approche totalement orientée vers JavaScript, sans SQL,
avec de la manipulation d'objets. Elle est cependant encore peu répandue (IE10 avec préfixe, Chrome et
Firefox avec préfixe) ; et demande une phase d'apprentissage supplémentaire même pour les développeurs
déjà aguerris avec SQL.
Web storage
Prise en charge : 
Pour les versions d'Internet Explorer antérieures à IE8, il existe une interface nommée userData qui alloue 1
Mo par domaine et qui fonctionne sensiblement de la même manière. Pour l'exploiter, il faudra cependant
adapter les fonctions au cas par cas, ou bien passer par un framework unifiant toutes les méthodes d'appel
en fonction du stockage disponible.
Web sockets
●
Liens :
– http://dev.opera.com/articles/view/web-storage/
– https://developers.google.com/web-toolkit/doc/latest/DevGuideHtm
– https://developer.mozilla.org/en-US/docs/Web/Guide/DOM/Storag
– http://msdn.microsoft.com/en-us/library/cc197062(VS.85).aspx#_d
– http://theburningmonk.com/2010/12/having-fun-with-html5-local-
– http://diveintohtml5.info/detect.html
Web sql
121
Web sql
Ouverture d'une base de données :
html5rocks.webdb.db = null;
html5rocks.webdb.open = function()
{
var dbSize = 5 * 1024 * 1024; // 5MB
html5rocks.webdb.db = openDatabase("Todo", "1.0", "Todo manager", dbSize);
}
html5rocks.webdb.onError = function(tx, e)
{
console.log("There has been an error: " + e.message);
}
html5rocks.webdb.onSuccess = function(tx, r)
{
// re-render the data.
// loadTodoItems is defined in Step 4a
html5rocks.webdb.getAllTodoItems(loadTodoItems);
}
Web sql
Creation d'une table :
html5rocks.webdb.createTable = function()
{
// Récupération du handle de la database
var db = html5rocks.webdb.db;
db.transaction(function(tx)
{
tx.executeSql("CREATE TABLE IF NOT EXISTS " +
"todo(ID INTEGER PRIMARY KEY ASC, todo TEXT, added_on
DATETIME)", []);
});
}
Web sql
Ajout d'une donnée dans une table :
html5rocks.webdb.addTodo = function(todoText)
{
// Récupération du handle de la database
var db = html5rocks.webdb.db;
db.transaction(function(tx)
{
var addedOn = new Date();
tx.executeSql("INSERT INTO todo(todo, added_on) VALUES (?,?)",
[todoText, addedOn],
html5rocks.webdb.onSuccess,
html5rocks.webdb.onError);
});
}
Web sql
Sélection d'une donnée dans une table :
html5rocks.webdb.getAllTodoItems = function(renderFunc)
{
// Récupération du handle de la database
var db = html5rocks.webdb.db;
db.transaction(function(tx)
{
tx.executeSql("SELECT * FROM todo", [], renderFunc,
html5rocks.webdb.onError);
});
}
Web sql
Mise en forme des données issue de la base de données :
function loadTodoItems(tx, rs)
{
var rowOutput = "";
var todoItems = document.getElementById("todoItems");
for (var i=0; i < rs.rows.length; i++)
{
rowOutput += renderTodo(rs.rows.item(i));
}
todoItems.innerHTML = rowOutput;
}
function renderTodo(row)
{
return "<li>" + row.todo +
" [<a href='javascript:void(0);' onclick='html5rocks.webdb.deleteTodo(" +
row.ID +");'>Delete</a>]</li>";
}
Web sql
Suppression d'une données dans une table :
html5rocks.webdb.deleteTodo = function(id)
{
// Récupération du handle de la database
var db = html5rocks.webdb.db;
db.transaction(function(tx)
{
tx.executeSql("DELETE FROM todo WHERE ID=?", [id],
html5rocks.webdb.onSuccess,
html5rocks.webdb.onError);
});
}
Web sql
Initialisation :
....
function init()
{
html5rocks.webdb.open();
html5rocks.webdb.createTable();
html5rocks.webdb.getAllTodoItems(loadTodoItems);
}
</script>
<body onload="init();">
Web sql
●
Liens :
– http://www.w3.org/TR/webdatabase/
– http://www.w3.org/TR/IndexedDB/
– http://html5sql.com/index.html
Web worker
130
Web worker
Vérification du support :
if(typeof(Worker)!=="undefined")
{
// Yes! Web worker support!
// Some code.....
}
else
{
// Sorry! No Web Worker support..
}
Web worker
Création d'un worker fichier « workers.js » :
var i=0;
function timedCount()
{
i=i+1;
postMessage(i);
setTimeout("timedCount()",500);
}
timedCount();
Web worker
Création d'un worker objet :
if (typeof(w)=="undefined")
{
w = new Worker("demo_workers.js");
}
Il est possible de déclarer un handle de messages associé au worker :
w.onmessage=function(event)
{
document.getElementById("result").innerHTML = event.data;
};
Web worker
Arrêt d'un worker :
w.terminate();
Exemple complet :
<!DOCTYPE html>
<html>
<body>
<p>Count numbers: <output id="result"></output></p>
<button onclick="startWorker()">Start Worker</button>
<button onclick="stopWorker()">Stop Worker</button>
<br><br>
<script>
var w;
function startWorker()
{
If (typeof(Worker) !== "undefined")
{
if(typeof(w)=="undefined")
{
w = new Worker("demo_workers.js");
}
w.onmessage = function (event)
{
document.getElementById("result").innerHTML=event.data;
};
} else {
document.getElementById("result").innerHTML="Sorry, your browser does not support Web Workers...";
}
}
function stopWorker()
{
w.terminate();
}
</script>
</body>
</html>
Web worker
●
Liens :
– https://developer.mozilla.org/en-US/docs/Web/Guide/Performance
– http://www.siteduzero.com/informatique/tutoriels/html5-web-work
– http://blogs.msdn.com/b/davrous/archive/2011/07/08/introduction-
– http://www.w3schools.com/html/html5_webworkers.asp
–
Application offline
137
App. offline
L’application cache repose principalement sur l’utilisation d’un fichier “manifest” à
ajouter aux pages HTML de votre site.
Tout d’abord, créons donc une structure basique de page web :
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
#main{
width:900px;
margin:auto;
}
</style>
</head>
<body>
<div id="main">
<h1>Ceci est mon application offline</h1>
<img src="earth-folder.png" />
</div>
</body>
</html>
App. offline
Afin d’utiliser le cache d’application, il va falloir déclarer un fichier manifest.
Ce fichier se déclare dans la balise html comme ceci :
<html manifest="site.manifest">
Une fois déclaré, il faut bien sûr créer le fichier manifest en question. Appelons le nôtre
“site.manifest”.
Dans ce fichier, qui commence obligatoirement par la ligne “CACHE MANIFEST”,
nous allons déclarer les fichiers qui doivent être mis en cache :
CACHE MANIFEST
# Version 0.1
index.html
earth-folder.png
App. offline
On peut également y ajouter des commentaires. Chaque ligne de commentaire doit commencer par #. Il est important
de versionner son fichier manifest via un commentaire, afin que le navigateur détecte par la suite les changements
dans le fichier.
Notons qu’il est possible d’utiliser des URL absolues (http://www.mon-url.com/absolue/fichier.html).
Il est possible d’ajouter différentes sections à notre fichier manifest :
● CACHE, il s’agit de la section par défaut qui liste les fichiers à mettre en cache.
● NETWORK, qui liste les fichiers qui nécessitent obligatoirement une connexion
internet.
● FALLBACK, qui liste les fichiers qui, au cas où ils ne soient pas accessibles
en ligne, doivent renvoyer vers d’autres fichiers.
L’exemple suivant représente un site web classique dont la page d’accueil, le CSS et les images sont mises en cache.
Si l’utilisateur se connecte à la page d’accueil en étant hors ligne, la page offline.html lui est présentée au lieu
d’index.html. Il est donc informé qu’il est déconnecté. Par conséquent il ne pourra pas accéder aux autres pages
du site, puisque la section NETWORK spécifie via une étoile “*”, que tous les autres fichiers requièrent une connexion
internet.
CACHE MANIFEST
# v0.1
CACHE:
index.html
css/style.css
img/logo.png
FALLBACK:
/ /offline.html
NETWORK:
*
App. offline
Le .htaccess :
Nous arrivons maintenant au passage (un peu) délicat. Il va falloir déclarer le MIME-type du fichier manifest.
Ceci se fait par l’intermédiaire du fichier de configuration de serveur. Dans la grande majorité des cas vous utiliserez
un fichier .htaccess pour les projets PHP.
Créez donc un fichier .htaccess dans le répertoire de votre application et ajoutez-y simplement la ligne :
AddType text/cache-manifest manifest
Dans cette ligne, on déclare que tous les fichiers se terminant par “manifest” ont pour MIME-type
“text/cache-manifest”.
App. offline
Test de l’application hors ligne :
Afin de pouvoir tester localement notre application, nous allons devoir passer par Apache (et oui, faites chauffer vos WAMP
/ MAMP / LAMP !).
Plaçons notre application dans le dossier de votre serveur (www pour WAMP) et rendez-vous sur l’adresse http://localhost/
Si tout se passe bien, votre page s’affiche.
Maintenant stoppez les services de WAMP, puis rafraîchissez la page.
Alors qu’une page classique aurait naturellement fait afficher une belle erreur 404… Votre page est toujours là !
Ouvrez maintenant la console de votre navigateur si celui-ci en possède une (pour Chrome, elle se trouve dans Outils,
Outils de développement, onglet Console).
On peut y voir ceci :
Creating Application Cache with manifest http://localhost/le-chemin-vers-votre-manifest
Application Cache Checking event
Application Cache Downloading event
Application Cache Progress event (0 of 3)
... (1 of 3)
... (2 of 3)
... (3 of 3)
Application Cache Cached event
On y voit en effet tous les événements qui ont lieu lorsque votre navigateur met à jour son AppCache. Les plus coriaces
d’entre vous souhaiterons pouvoir intercepter ces événements pour pouvoir effectuer des traitements au moment du
déclenchement de ces événements.
Ces événements seront détaillés dans la partie “aller plus loin” de ce tutoriel.
App. offline
Mise à jour du manifest :
Attention soyez bien attentif à présent ! La phrase suivante a de quoi perturber : une fois votre application
dans l’AppCache grâce au fichier manifest, c’est cette version offline qui a la priorité sur la version en ligne !
Pourquoi ?
Tout simplement parce que vous lui avez justement dit de le stocker dans le cache ! C’est exactement comme
lorsque votre navigateur garde en mémoire une image ou un CSS sur un site, afin de ne pas avoir à le
télécharger à nouveau. Seulement, c’est un peu plus perturbant lorsqu’il est question d’un fichier HTML,
je le reconnais… Et donc, comment fait-on pour mettre à jour le cache avec la version en ligne ?
L’Application Cache sera mis à jour si :
● L’utilisateur vide son cache manuellement.
● Le fichier manifest change.
● Le cache est mis à jour avec du code Javascript.
Voilà pourquoi il était important d’insérer un numéro de version dans un commentaire ! Il suffit de changer
ce numéro de version pour obliger l’AppCache du client à se mettre à jour. Si vous effectuez peu de mises à
jour (dans le cas d’un site vitrine par exemple) c’est la meilleure solution. Par contre, si vous avez besoin
que le client soit en permanence à jour, on préfèrera la version Javascript. Et encore une fois, c’est dans la
section “Aller plus loin” que ça se passe !
App. offline
Aller plus loin avec le manifest :
La solution peut être de créer un service générant le manifest en changeant, d’une part, de version à chaque
nouvel article publié et, d’autre part, en listant les URLs des derniers articles dans le cache explicite. Le
chargement prendra plus de temps mais le lecteur pourra consulter l’article hors-ligne sans plus d’effort.
Attention, les pages implicites qui déclarent le manifest sans être listées dans ce dernier y sont ajoutées et
seront téléchargées elles aussi lors de la mise à jour du cache.
Soyez prudent quand vous activez le manifest et ne multipliez pas les pages. Dans le cas du blog par exemple
les pages affichant les articles ne doivent pas utiliser le manifest. Le lecteur ne souhaite certainement pas
télécharger l’ensemble des articles qu’il a déjà lu à chaque nouvel article.
Cette solution minimaliste peut convenir à certains, mais elle n’est pas applicable pour un site dont le contenu
change beaucoup ou pour un site à fort trafic tant l’utilisation du cache est mauvaise.
Pour optimiser l’utilisation du cache, il faut le considérer comme la vue statique de l’application qui évoluera au
gré des changements d’interface et non au gré du contenu. Le contenu dynamique devra être servi par des
requêtes asynchrones. Pour la mise en cache et le fonctionnement il faudra utiliser les nouvelles API
JavaSript : LocalStorage et document.onLine. De cette manière, le manifest redeviendra un fichier statique
évoluant au gré des versions de l’application.
Pour garantir l’indexation du contenu par les moteurs de recherche et assurer la compatibilité avec d’anciens
navigateurs, prévoyez toujours un mode dégradé sans manifest ni contenu asynchrone.
App. offline
Notes de sécurité :
Notez que le cache est maintenu par nom de domaine. Il n’existe qu’une seule instance du même manifest
pour un serveur. Pour les serveurs hébergeant plusieurs applications, l’utilisation d’hôte virtuel est plus que
conseillée.
Le cache ne doit jamais contenir de données confidentielles. Les pages de login et tous services de sécurité
doivent être exclus du cache. Ne les listez jamais dans le manifest sauf pour les exclure et surtout n’intégrez
pas le manifest dans ces pages.
Informez l’utilisateur sur les dangers de ce service et surtout laissez le choisir d’activer ou non le
fonctionnement hors ligne. En effet si le navigateur lui-même n’est pas protégé, toute personne y ayant
accès pourra consulter le cache. Pour limiter le problème vous pouvez activer le service en stockant un
cookie sur le navigateur si l’utilisateur active le mode hors ligne. Ainsi le lecteur devra répéter l’opération
pour tous les navigateurs sur lesquels il souhaite consulter le site.
En dehors de ces règles de sécurité basiques, toutes les règles de sécurité inhérentes aux sites web
s’appliquent.
App. offline
L’API Javascript HTML5 possède un objet window.applicationCache. Cet objet permet de :
● connaître les états du cache
● attacher des traitements aux événements
● faire une mise à jour du cache
● changer le cache actuel
Voici la classe ApplicationCache telle qu’elle est donnée par le WHATWG :
interface ApplicationCache
{
// update status
const unsigned short UNCACHED = 0;
const unsigned short IDLE = 1;
const unsigned short CHECKING = 2;
const unsigned short DOWNLOADING = 3;
const unsigned short UPDATEREADY = 4;
const unsigned short OBSOLETE = 5;
readonly attribute unsigned short status;
// updates
void update();
void swapCache();
// events
attribute Function onchecking;
attribute Function onerror;
attribute Function onnoupdate;
attribute Function ondownloading;
attribute Function onprogress;
attribute Function onupdateready;
attribute Function oncached;
attribute Function onobsolete;
};
ApplicationCache implements EventTarget;
App. offline
Ainsi on peut tester le statut actuel :
if (webappCache.status == window.applicationCache.UPDATEREADY)
Ou avec un switch :
switch (appCache.status) {
case appCache.UNCACHED: // UNCACHED == 0
return 'UNCACHED';
break;
case appCache.IDLE: // IDLE == 1
return 'IDLE';
break;
…
Mais il est préférable de passer par la gestion d’événements pour détecter lorsque l’Application Cache change de statut :
var webappCache = window.applicationCache;
webappCache.addEventListener("updateready", updateCache, false);
webappCache.update();
function updateCache()
{
webappCache.swapCache();
alert("Une nouvelle version est disponible.nVeuillez rafraîchir la page pour mettre à jour.");
}
App. offline
● La méthode update() force le lancement du processus de mise à jour du cache.
● addEventListener(“updateready”, updateCache, false) lancera la fonction updateCache dès que le
statut de l’AppCache passera en “updateready”.
● swapCache() permet d’échanger l’ancien cache avec le nouveau cache, ce qui finalise l’opération.
Si vous souhaitez trouver de plus amples informations sur le sujet, je vous invite à vous rendre sur la
page Application Cache du WHATWG, où sont listés tous les status que peut prendre
applicationcache.status, et tous les événements associés.
Dernière petite remarque, il est possible de tester si l’utilisateur est connecté à internet ou non avec la
propriété :
navigator.onLine
Et voilà ! Vous avez tous les outils en main pour réaliser de superbes applications web ! Il y a fort à
parier que ces applications deviendront le standard sur les smartphones d’ici quelques années,
puisqu’elles fonctionnent aussi bien sur iPhone qu’Android.
Couplé avec une balise canvas, on pourra par exemple jouer à des jeux vidéos en 3D dans le
navigateur, qui seront compatibles avec tous les mobiles ! Pas besoin de s’embêter à développer
plusieurs versions pour chaque OS mobile, du HTML/CSS et Javascript suffisent !
App. offline
Voici le code source de la page en question :
<!DOCTYPE html>
<html manifest="site.manifest">
<head>
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-
scale=1.0"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-icon" href="earth-folder.png">
<link rel="apple-touch-icon-precomposed" href="earth-folder.png">
<link rel="apple-touch-startup-image" href="earth-folder.png" />
<style type="text/css">
#main{
width:900px;
margin:auto;
}
</style>
</head>
<body>
<div id="main">
<h1>Cette page est accessible hors ligne</h1>
<p>Elle possède une icone d'application pour les smartphones.</p>
<img src="earth-folder.png" />
</div>
</body>
</html>
App. offline
Le fichier site.manifest :
CACHE MANIFEST
# Version 0.4
exemple-application-cache-manifest-html5.html
earth-folder.png
Le .htaccess :
AddType text/cache-manifest manifest
App. offline
●
Liens :
– http://blog.xebia.fr/2010/12/02/application-hors-ligne-avec-html5-
– http://diveintohtml5.info/offline.html
– http://html5demo.braincracking.org/demo/onLine.php
Framework JS
152
Framework JS
Une famille nombreuse :
JS client :
● http://prototypejs.org/
● http://script.aculo.us/
● http://mootools.net/
● http://www.sencha.com/products/touch
● http://www.sencha.com/products/extjs
● http://www.sencha.com/products/gxt
● http://yuilibrary.com/
● http://dojotoolkit.org/
● http://www.angularjs.org/
● http://meteor.com/
● http://jquery.com/
● http://jquerytools.org/
● http://jqueryui.com/
● http://jquerymobile.com/
● http://jqtjs.com/
● http://www.jqmobi.com/
● http://www.bbc.co.uk/glow/
● http://www.midorijs.com/
● https://developers.google.com/web-toolkit/?hl=fr
JS server :
● http://nodejs.org/
Comparatifs :
● http://en.wikipedia.org/wiki/Comparison_of_JavaScript_frameworks
● http://en.wikipedia.org/wiki/List_of_JavaScript_libraries
jQuery
154
jQuery
● La naissance de JavaScript :
● 1995 : Brendan Eich développe pour Netscape Communications
Corporation, un langage de script, appelé Mocha, puis LiveScript et
finalement JavaScript
● Javascript est intégré dans le navigateur Netscape 2. Succès immédiat.
● Javascript n'est pas java !! D'un point de vue des propriétés, Javascript est
plus proche du langage python que du java.
● La guerre des navigateurs :
● Netscape et Microsoft (avec JScript dans Internet Explorer) ont développé
leur propre variante de JavaScript avec des fonctionnalités supplémentaires
et incompatibles, notamment dans la manipulation du DOM (modèle objet
du navigateur WEB)
● 1997 : Adoption du standard ECMAScript.
Les spécifications sont rédigées dans le document Standard ECMA-262.
jQuery
Définition de jQuery :
● Une bibliothèque javascript open-source et cross-browser
● Elle permet de traverser et manipuler très facilement l'arbre DOM des pages web à l'aide
d'une syntaxe fortement similaire à celle d'XPath.
● JQuery permet par exemple de changer/ajouter une classe CSS, créer des animations,
modifier des attributs, etc.
● Gérer les événements javascript
● Faire des requêtes AJAX simplement
jQuery
Ce que jQuery n’est pas :
● Un substitut pour apprendre JavaScript
● jQuery est très puissant et très pratique, mais vous devez néanmoins
connaitre les bases de Javascript, notamment la partie “objet” du langage.
● Voir des livres comme :
“Object Oriented Javascript de Stoyan Stefanov” ou
“jQuery, novice to ninja” (google est votre ami)
● Une réponse à tout
● Utilisez jQuery uniquement lorsque c’est nécessaire. On commence toujours
par HTML+CSS avant de chercher des plugins jQuery magiques.
● De nombreuses UI sont pures html+CSS
jQuery
Une simple bibliothèque à importer :
Disponible sur le site de Jquery : http://jquery.com/
<script type="text/javascript" src="jquery.js"></script>
Ou directement sur Google code :
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min
.js">
</script>
jQuery
La fonction jQuery() :
● jQuery repose sur une seule fonction : jQuery() ou $()
● C’est une fonction JavaScript
● Elle accepte des paramètres
● Elle retourne un objet
● $ : Syntaxe issue de « Prototype »
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3
Formation html3 css3

Más contenido relacionado

Destacado

Historia del teatro en imágenes
Historia del teatro en imágenesHistoria del teatro en imágenes
Historia del teatro en imágenesinicial4jfk
 
Cf oqueagregavaloralnegocio
Cf oqueagregavaloralnegocioCf oqueagregavaloralnegocio
Cf oqueagregavaloralnegocioRodrigo García
 
Bluetooth on GNU Linux
Bluetooth on GNU LinuxBluetooth on GNU Linux
Bluetooth on GNU LinuxThierry Gayet
 
Head turn
Head turn Head turn
Head turn catavrio
 
Quel est le_prix_de_la_beaute
Quel est le_prix_de_la_beauteQuel est le_prix_de_la_beaute
Quel est le_prix_de_la_beautecatavrio
 
Unidad+7+apliquemos+elementos+de+geometria+analitica.
Unidad+7+apliquemos+elementos+de+geometria+analitica.Unidad+7+apliquemos+elementos+de+geometria+analitica.
Unidad+7+apliquemos+elementos+de+geometria+analitica.Roxana Abarca Gonzalez
 
Planificación para la presentación del tema señalización y señalética
Planificación para la presentación del tema señalización y señaléticaPlanificación para la presentación del tema señalización y señalética
Planificación para la presentación del tema señalización y señaléticaAdis Corona
 
Comunicación humana por medios masivos, Itzamar González Vargas, g5, periodo ...
Comunicación humana por medios masivos, Itzamar González Vargas, g5, periodo ...Comunicación humana por medios masivos, Itzamar González Vargas, g5, periodo ...
Comunicación humana por medios masivos, Itzamar González Vargas, g5, periodo ...Itza González Vargas
 
La loi du_bon_samaritain
La loi du_bon_samaritainLa loi du_bon_samaritain
La loi du_bon_samaritaincatavrio
 
L'histoire de pepe
L'histoire de pepeL'histoire de pepe
L'histoire de pepecatavrio
 
Les amis arrivent
Les amis arriventLes amis arrivent
Les amis arriventcatavrio
 
proceso de la evaluación
proceso de la evaluación proceso de la evaluación
proceso de la evaluación Karla Grohmann
 
Redes locales basico
Redes locales basicoRedes locales basico
Redes locales basicofrangaco2014
 

Destacado (20)

Etna
EtnaEtna
Etna
 
Historia del teatro en imágenes
Historia del teatro en imágenesHistoria del teatro en imágenes
Historia del teatro en imágenes
 
Cf oqueagregavaloralnegocio
Cf oqueagregavaloralnegocioCf oqueagregavaloralnegocio
Cf oqueagregavaloralnegocio
 
Bluetooth on GNU Linux
Bluetooth on GNU LinuxBluetooth on GNU Linux
Bluetooth on GNU Linux
 
Head turn
Head turn Head turn
Head turn
 
vercado virtual
vercado virtualvercado virtual
vercado virtual
 
Quel est le_prix_de_la_beaute
Quel est le_prix_de_la_beauteQuel est le_prix_de_la_beaute
Quel est le_prix_de_la_beaute
 
L Afrique!!!
L Afrique!!!L Afrique!!!
L Afrique!!!
 
Unidad+7+apliquemos+elementos+de+geometria+analitica.
Unidad+7+apliquemos+elementos+de+geometria+analitica.Unidad+7+apliquemos+elementos+de+geometria+analitica.
Unidad+7+apliquemos+elementos+de+geometria+analitica.
 
Planificación para la presentación del tema señalización y señalética
Planificación para la presentación del tema señalización y señaléticaPlanificación para la presentación del tema señalización y señalética
Planificación para la presentación del tema señalización y señalética
 
Comunicación humana por medios masivos, Itzamar González Vargas, g5, periodo ...
Comunicación humana por medios masivos, Itzamar González Vargas, g5, periodo ...Comunicación humana por medios masivos, Itzamar González Vargas, g5, periodo ...
Comunicación humana por medios masivos, Itzamar González Vargas, g5, periodo ...
 
La loi du_bon_samaritain
La loi du_bon_samaritainLa loi du_bon_samaritain
La loi du_bon_samaritain
 
Bitstrips,
Bitstrips, Bitstrips,
Bitstrips,
 
L'histoire de pepe
L'histoire de pepeL'histoire de pepe
L'histoire de pepe
 
Catedra upecista
Catedra upecistaCatedra upecista
Catedra upecista
 
Planificador de proyectos
Planificador de proyectosPlanificador de proyectos
Planificador de proyectos
 
Les amis arrivent
Les amis arriventLes amis arrivent
Les amis arrivent
 
Realidad Aumentada
Realidad AumentadaRealidad Aumentada
Realidad Aumentada
 
proceso de la evaluación
proceso de la evaluación proceso de la evaluación
proceso de la evaluación
 
Redes locales basico
Redes locales basicoRedes locales basico
Redes locales basico
 

Similar a Formation html3 css3

HTML5, le web de demain - BNSA
HTML5, le web de demain - BNSAHTML5, le web de demain - BNSA
HTML5, le web de demain - BNSABNSA - Aquitaine
 
Formation html5 css3 java script
Formation html5 css3 java scriptFormation html5 css3 java script
Formation html5 css3 java scriptArrow Group
 
Prsentationhtml5 html5 ii twebteck
Prsentationhtml5 html5 ii twebteckPrsentationhtml5 html5 ii twebteck
Prsentationhtml5 html5 ii twebteckTECOS
 
Cours_1 - HTML5 et JS.ppt
Cours_1 - HTML5 et JS.pptCours_1 - HTML5 et JS.ppt
Cours_1 - HTML5 et JS.pptRihabBENLAMINE
 
Prsentationhtml5 html5 ii twebteck
Prsentationhtml5 html5 ii twebteckPrsentationhtml5 html5 ii twebteck
Prsentationhtml5 html5 ii twebteckTECOS
 
Formation html5 CSS3 offerte par ippon 2014
Formation html5 CSS3 offerte par ippon 2014Formation html5 CSS3 offerte par ippon 2014
Formation html5 CSS3 offerte par ippon 2014Ippon
 
HTML5... La révolution maintenant!
HTML5... La révolution maintenant!HTML5... La révolution maintenant!
HTML5... La révolution maintenant!CARA_Lyon
 
HTML5... La révolution maintenant!
HTML5... La révolution maintenant!HTML5... La révolution maintenant!
HTML5... La révolution maintenant!CARA_Lyon
 
Tendances Futures du Web - GTI780 & MTI780 - ETS - A09
Tendances Futures du Web - GTI780 & MTI780 - ETS - A09Tendances Futures du Web - GTI780 & MTI780 - ETS - A09
Tendances Futures du Web - GTI780 & MTI780 - ETS - A09Claude Coulombe
 
Wygday 2011 - Introduction à HTML5
Wygday 2011 - Introduction à HTML5Wygday 2011 - Introduction à HTML5
Wygday 2011 - Introduction à HTML5wyggio
 
Rapport de mini projet de programation web
Rapport de mini projet de programation webRapport de mini projet de programation web
Rapport de mini projet de programation webMOHAMMED MOURADI
 
Html5-Devfest Yaoundé 2013
Html5-Devfest Yaoundé 2013Html5-Devfest Yaoundé 2013
Html5-Devfest Yaoundé 2013gdgyaounde
 
Chap1-Introduction au HTML 5.pdf
Chap1-Introduction au HTML 5.pdfChap1-Introduction au HTML 5.pdf
Chap1-Introduction au HTML 5.pdfENS
 
Rmll2010 Html5 Css3
Rmll2010 Html5 Css3Rmll2010 Html5 Css3
Rmll2010 Html5 Css3Fnot
 

Similar a Formation html3 css3 (20)

HTML5, le web de demain - BNSA
HTML5, le web de demain - BNSAHTML5, le web de demain - BNSA
HTML5, le web de demain - BNSA
 
Html5 & ie
Html5 & ieHtml5 & ie
Html5 & ie
 
Formation html5 css3 java script
Formation html5 css3 java scriptFormation html5 css3 java script
Formation html5 css3 java script
 
Prsentationhtml5 html5 ii twebteck
Prsentationhtml5 html5 ii twebteckPrsentationhtml5 html5 ii twebteck
Prsentationhtml5 html5 ii twebteck
 
Cours_1 - HTML5 et JS.ppt
Cours_1 - HTML5 et JS.pptCours_1 - HTML5 et JS.ppt
Cours_1 - HTML5 et JS.ppt
 
Cours html5
Cours html5Cours html5
Cours html5
 
Prsentationhtml5 html5 ii twebteck
Prsentationhtml5 html5 ii twebteckPrsentationhtml5 html5 ii twebteck
Prsentationhtml5 html5 ii twebteck
 
Formation html5 CSS3 offerte par ippon 2014
Formation html5 CSS3 offerte par ippon 2014Formation html5 CSS3 offerte par ippon 2014
Formation html5 CSS3 offerte par ippon 2014
 
HTML5... La révolution maintenant!
HTML5... La révolution maintenant!HTML5... La révolution maintenant!
HTML5... La révolution maintenant!
 
HTML5... La révolution maintenant!
HTML5... La révolution maintenant!HTML5... La révolution maintenant!
HTML5... La révolution maintenant!
 
Tendances Futures du Web - GTI780 & MTI780 - ETS - A09
Tendances Futures du Web - GTI780 & MTI780 - ETS - A09Tendances Futures du Web - GTI780 & MTI780 - ETS - A09
Tendances Futures du Web - GTI780 & MTI780 - ETS - A09
 
Wygday 2011 - Introduction à HTML5
Wygday 2011 - Introduction à HTML5Wygday 2011 - Introduction à HTML5
Wygday 2011 - Introduction à HTML5
 
Atelier template
Atelier templateAtelier template
Atelier template
 
Plici - PréSentation V2
Plici - PréSentation V2Plici - PréSentation V2
Plici - PréSentation V2
 
Rapport de mini projet de programation web
Rapport de mini projet de programation webRapport de mini projet de programation web
Rapport de mini projet de programation web
 
Association 2 0
Association 2 0Association 2 0
Association 2 0
 
Association 2 0
Association 2 0Association 2 0
Association 2 0
 
Html5-Devfest Yaoundé 2013
Html5-Devfest Yaoundé 2013Html5-Devfest Yaoundé 2013
Html5-Devfest Yaoundé 2013
 
Chap1-Introduction au HTML 5.pdf
Chap1-Introduction au HTML 5.pdfChap1-Introduction au HTML 5.pdf
Chap1-Introduction au HTML 5.pdf
 
Rmll2010 Html5 Css3
Rmll2010 Html5 Css3Rmll2010 Html5 Css3
Rmll2010 Html5 Css3
 

Formation html3 css3

  • 1. Formation web html5 / css3 Thierry GAYET - Thierry.Gayet@gmail.fr
  • 2. TIMING DE LA FORMATION Timing journalier : ● Matin : 09h00-10h30 : première partie 10h30-10h45 : pause 10h45-13h00 : seconde partie ● Pause déjeuner ● Après-midi : 14h00-15h30 : troisième partie 15h30-15h45 : pause 15h45-17h00 : quatrième partie ● Questions libres. Timing journalier : ● Matin : 09h00-10h30 : première partie 10h30-10h45 : pause 10h45-13h00 : seconde partie ● Pause déjeuner ● Après-midi : 14h00-15h30 : troisième partie 15h30-15h45 : pause 15h45-17h00 : quatrième partie ● Questions libres. merci de signaler toute contrainte de temps sur cette période dès le début
  • 3. PLAN DE LA FORMATION  Historique du web & standards  Nouveaux éléments & attributs  Le formulaires web forms  Les microformats (microdata)  Audio & vidéo  Dessin avec canvas  Géolocalisation  Interraction avec les fichiers  Drap & drop  Push de données  Web messaging  Web sockets  Web storage  Web sql  Web workers  Application hors ligne  Exemples de CSS3  Jquery par l'exemple
  • 5. Historique 5 Pour mieux comprendre la transition que le Web vit en ce moment, voici un bref historique de ce changement de cap. → 1998 : En prônant les avantages du XML, le W3C décide de ne plus continuer le développement du HTML (qui en est à la version 4.01) et élabore une première spécification du XHTML (v 1.0). Cette version est un amalgame de la syntaxe du HTML et des normes et standards XML. Ce fut une bonne décision, car le XML étant strict sur ses normes, ça met de l’avant le souci d’un code bien structuré et d’une uniformité entre les sites Web. → 2006 : 8 ans après cette décision, le W3C la remet en question et commence à penser que le XML (et le XHTML) n’est peut être pas la voie du futur en conception Web. Il décide donc de travailler sur une nouvelle spécification du HTML tout en continuant l’évolution du XHTML (v2.0). Plusieurs groupes (Mozilla, Opera, Google, …) viennent à travailler conjointement avec le W3C sur le HTML 5. Fait à noter : certains individus n’ont jamais arrêté de travailler sur le HTML depuis 1998. Pour en savoir plus sur la période 1998-2006, vous pouvez lire sur le groupe WHATWG (www.whatwg.org). → 2009 : Le W3C arrête complètement de travailler sur le XHTML v2.0 et toutes les ressources sont redirigées vers le HTML 5. La philosophie est désormais : pureté du design, par-dessus l’idéologie d’être rétro-compatible Adieu le XHTML ! Les navigateurs restent compatibles avec le XHTML, mais l’emphase est maintenant sur l’implémentation des spécifications du HTML 5. Actuellement, il y a 2 spécifications du HTML 5 qui sont développées en parallèle : ● la version du WHATWG ● la version du W3C Les deux groupes travaillent « relativement » conjointement, mais ils divergent sur certains points. Si vous devez choisir une spécification, je vous conseille celle du W3C, qui est moins expérimentale. Les spécifications du HTML 5 évoluent constamment. Ceci explique même pourquoi WHATWG a même décidé de supprimer le « 5 » de HTML 5. Les navigateurs doivent donc toujours regarder les changements aux spécifications pour se mettre à jour.
  • 6. Historique Quelques dates à retenir : – 1991 HTML – 1994 HTML 2 – 1996 CSS 1 + JavaScript – 1997 HTML 4 – 1998 CSS 2 – 1999 HTML 4.01 – 2000 XHTML 1 – 2002 Tableless design – 2004 WHATWG – 2005 AJAX – 2007 XHTML 2 boudé – 2007 Le W3C récupère les travaux du WHATWG – 2009 Arrêt des travaux sur XHTML 2 – 2010 HTML 5 + JavaScript API + CSS 3 6
  • 7. HISTORIQUE ● Liens : – http://www.zdnet.fr/actualites/html5-petite-histoire-et-promesses-d – http://www.weblife.fr/wp-content/uploads/2012/07/html5-histoire-
  • 9. HTML 5 ● <!DOCTYPE html> & <meta charset="UTF-8"> ● Nouvelles balises ● Balises vidéos et audio ● Nouveaux champs de formulaire ● Nouveaux attributs notamment autofocus, placeholder ● Certaines balises et attributs dépréciés : frame, frameset, big, font, center, acronym, ... ● Intégration de SVG ● MicroData ● ... LES NOUVEAUX ELEMENTS → Nouvelles balises : ● <section> ● <header>/<footer> ● <nav> ● <article> ● <aside> ● <hgroup> ● <time> ● <canvas> ● <audio>/<video> ● Et d’autres…
  • 10. CSS 3 ● Multi-colonnes ● Bordures ● Gradients ● Webfonts ● Manipulation de texte ● Animations & transitions ● Flexible box model ● Nouveaux selecteurs ● Media Queries ● ... LES NOUVEAUX ELEMENTS
  • 11. JavaScript ● Geolocation ● WebWorkers ● WebSockets ● Orientation ● Notification ● sessionStorage & localStorage ● Web SQL database & IndexedDB ● ... LES NOUVEAUX ELEMENTS
  • 12. HTML 5 + JavaScript ● Canvas 2D ● Intégration audio et vidéo ● Mode offline ● Gestion de l'historique ● Edition de contenu ● Drag & Drop ● Custom data attribute ● ... LES NOUVEAUX ELEMENTS
  • 13. CSS 3 + JavaScript ● Selectors ● Classlist LES NOUVEAUX ELEMENTS
  • 14. WebGL ● Avant Chrome 9, lancer chrome avec --enable-webgl ● Sous Firefox 4, about:config puis enable for all sites ● Exemple depuis Learning WebGL ● Body Browser de Google LES NOUVEAUX ELEMENTS
  • 15. A Venir ● Contacts API ● Webcam (Capture API) ● Device Orientation API ● Calendar API ● Speech input ● ... LES NOUVEAUX ELEMENTS
  • 17. Nouveaux types d'entrées dans HTML5 Ce que nous connaissons aujourd'hui comme étant HTML5 Forms ou HTML5 Web Forms a démarré sous le nom de Web Forms 2.0, une spécification pré-HTML5 créée par un groupe appelé WHATWG (Web Hypertext Applications Technology Working Group). La majeure partie du travail initial du WHATWG est devenue le point de départ ce que nous appelons maintenant HTML5 et l'effort Web Forms 2.0 fait à présent partie de la spécification HTML5 officielle, que vous pouvez consulter à l'adresse suivante : bit.ly/njrWvZ. Une partie non négligeable de la spécification est consacrée à de nouveaux types et attributs de contenu pour l'élément d'entrée, que vous trouverez à l'adresse suivante : Comme je l'ai mentionné précédemment, la spécification introduit 13 nouveaux types d'entrées à utiliser dans des formulaires : recherche, tél., url, e-mail, dateheure, date, mois, semaine, heure, dateheure-locale, numéro, plage, couleur. L'utilisation de ces nouveaux types est simple. Imaginons que je veuille insérer un nouveau champ d'e-mail sur un formulaire de commande. Comme vous pouvez le voir sur la Figure 1, j'ai modifié la page de commande du site Web de modèle Pâtisserie WebMatrix en lui ajoutant des champs, dont e- mail. LES WEBFORMS
  • 18. La balise <input> en HTML4 possède les propriétés suivante : Type Description text A free-form text field, nominally free of line breaks. password A free-form text field for sensitive information, nominally free of line breaks. checkbox A set of zero or more values from a predefined list. radio An enumerated value. submit A free form of button initiates form submission. file An arbitrary file with a MIME type and optionally a file name. image A coordinate, relative to a particular image's size, with the extra semantic that it must be the last value selected and initiates form submission. hidden An arbitrary string that is not normally displayed to the user. select An enumerated value, much like the radio type. textarea A free-form text field, nominally with no line break restrictions. button A free form of button which can initiates any event related to button. Exemple de formulaire : <form action="http://example.com/cgiscript.pl" method="post"> <p> <label for="firstname">first name: </label> <input type="text" id="firstname"><br /> <label for="lastname">last name: </label> <input type="text" id="lastname"><br /> <label for="email">email: </label> <input type="text" id="email"><br> <input type="radio" name="sex" value="male"> Male<br> <input type="radio" name="sex" value="female"> Female<br> <input type="submit" value="send"> <input type="reset"> </p> </form> LES WEBFORMS
  • 19. La balise <input> en HTML5 a évolué en incluant de nouvelles propriétés : Type Description datetime A date and time (year, month, day, hour, minute, second, fractions of a second) encoded according to ISO 8601 with the time zone set to UTC. datetime-local A date and time (year, month, day, hour, minute, second, fractions of a second) encoded according to ISO 8601, with no time zone information. date A date (year, month, day) encoded according to ISO 8601. month A date consisting of a year and a month encoded according to ISO 8601. week A date consisting of a year and a week number encoded according to ISO 8601. time A time (hour, minute, seconds, fractional seconds) encoded according to ISO 8601. number This accepts only numerical value. The step attribute specifies the precision, defaulting to 1. range The range type is used for input fields that should contain a value from a range of numbers. email This accepts only email value. This type is used for input fields that should contain an e-mail address. If you try to submit a simple text, it forces to enter only email address in email@eurogiciel.fr format. url This accepts only URL value. This type is used for input fields that should contain a URL address. If you try to submit a simple text, it forces to enter only URL address either in http://www.eurogiciel.fr format or in http://example.com format. Exemple de formulaire : <form action="demo_form.asp" autocomplete="on"> First name:<input type="text" name="fname"><br> Last name: <input type="text" name="lname"><br> E-mail: <input type="email" name="email" autocomplete="off"><br> <input type="submit"> </form> LES WEBFORMS
  • 20. Quelques exemples de formulaires : <form> <p><label>Customer name: <input></label></p> <fieldset> <legend> Pizza Size </legend> <p><label> <input type=radio name=size> Small </label></p> <p><label> <input type=radio name=size> Medium </label></p> <p><label> <input type=radio name=size> Large </label></p> </fieldset> </form> <form> <p><label>Customer name: <input></label></p> <fieldset> <legend> Pizza Size </legend> <p><label> <input type=radio name=size> Small </label></p> <p><label> <input type=radio name=size> Medium </label></p> <p><label> <input type=radio name=size> Large </label></p> </fieldset> <fieldset> <legend> Pizza Toppings </legend> <p><label> <input type=checkbox> Bacon </label></p> <p><label> <input type=checkbox> Extra Cheese </label></p> <p><label> <input type=checkbox> Onion </label></p> <p><label> <input type=checkbox> Mushroom </label></p> </fieldset> </form> LES WEBFORMS
  • 21. <form> <p><label>Customer name: <input></label></p> <p><label>Telephone: <input type=tel></label></p> <p><label>E-mail address: <input type=email></label></p> <fieldset> <legend> Pizza Size </legend> <p><label> <input type=radio name=size> Small </label></p> <p><label> <input type=radio name=size> Medium </label></p> <p><label> <input type=radio name=size> Large </label></p> </fieldset> <fieldset> <legend> Pizza Toppings </legend> <p><label> <input type=checkbox> Bacon </label></p> <p><label> <input type=checkbox> Extra Cheese </label></p> <p><label> <input type=checkbox> Onion </label></p> <p><label> <input type=checkbox> Mushroom </label></p> </fieldset> <p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900"></label></p> <p><label>Delivery instructions: <textarea></textarea></label></p> </form> LES WEBFORMS
  • 22. <form method="post" enctype="application/x-www-form-urlencoded" action="https://pizza.example.com/order.cgi"> <p><label>Customer name: <input name="custname"></label></p> <p><label>Telephone: <input type=tel name="custtel"></label></p> <p><label>E-mail address: <input type=email name="custemail"></label></p> <fieldset> <legend> Pizza Size </legend> <p><label> <input type=radio name=size value="small"> Small </label></p> <p><label> <input type=radio name=size value="medium"> Medium </label></p> <p><label> <input type=radio name=size value="large"> Large </label></p> </fieldset> <fieldset> <legend> Pizza Toppings </legend> <p><label> <input type=checkbox name="topping" value="bacon"> Bacon </label></p> <p><label> <input type=checkbox name="topping" value="cheese"> Extra Cheese </label></p> <p><label> <input type=checkbox name="topping" value="onion"> Onion </label></p> <p><label> <input type=checkbox name="topping" value="mushroom"> Mushroom </label></p> </fieldset> <p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900" name="delivery"></label></p> <p><label>Delivery instructions: <textarea name="comments"></textarea></label></p> <p><button>Submit order</button></p> </form> LES WEBFORMS
  • 23. <fieldset> <legend>Display</legend> <p><label><input type=radio name=c value=0 checked> Black on White</label> <p><label><input type=radio name=c value=1> White on Black</label> <p><label><input type=checkbox name=g> Use grayscale</label> <p><label>Enhance contrast <input type=range name=e list=contrast min=0 max=100 value=0 step=1></label> <datalist id=contrast> <option label=Normal value=0> <option label=Maximum value=100> </datalist> </fieldset> <fieldset name="clubfields" disabled> <legend> <label> <input type=checkbox name=club onchange="form.clubfields.disabled = !checked"> Use Club Card </label> </legend> <p><label>Name on card: <input name=clubname required></label></p> <p><label>Card number: <input name=clubnum required pattern="[-0-9]+"></label></p> <p><label>Expiry date: <input name=clubexp type=month></label></p> </fieldset> LES WEBFORMS
  • 24. <fieldset name="clubfields" disabled> <legend> <label> <input type=checkbox name=club onchange="form.clubfields.disabled = !checked"> Use Club Card </label> </legend> <p><label>Name on card: <input name=clubname required></label></p> <fieldset name="numfields"> <legend> <label> <input type=radio checked name=clubtype onchange="form.numfields.disabled = !checked"> My card has numbers on it </label> </legend> <p><label>Card number: <input name=clubnum required pattern="[-0-9]+"></label></p> </fieldset> <fieldset name="letfields" disabled> <legend> <label> <input type=radio name=clubtype onchange="form.letfields.disabled = !checked"> My card has letters on it </label> </legend> <p><label>Card code: <input name=clublet required pattern="[A-Za-z]+"></label></p> </fieldset> </fieldset> LES WEBFORMS
  • 25. LES WEBFORMS ● Liens : – http://diveintohtml5.info/forms.html – http://msdn.microsoft.com/fr-fr/magazine/hh547102.aspx – http://smashinghub.com/html5-web-forms-tutorials.htm – http://miketaylr.com/code/input-type-attr.html – http://miketaylr.com/code/html5-forms-ui-support.html – http://miketaylr.com/code/html5-textarea-attribute-support.html – http://www.whatwg.org/specs/web-apps/current-work/#the-textare – http://www.w3schools.com/html/html5_form_attributes.asp – http://www.standardista.com/html5/html5-web-forms/ – http://miketaylr.com/pres/html5/forms2.html – http://estelle.github.io/forms/#slide1
  • 27. Le microformat propose une syntaxe qui s’apparente à du HTML classique et s’applique bien en dehors de la norme HTML5 puisqu’il est compatible avec HTML4, ou XHTML1.0 par exemple. Il utilise l’attribut class et certaines valeurs bien précises dans le but de “baliser” un contenu afin qu’il soit interprété comme une donnée bien spécifique. Voici un exemple de code un peu plus parlant : <span class="hreview-aggregate"> <span class="item"> <span class="fn">Juiz Smart Mobile Admin</span> </span> <span class="rating"> Note de : <span class="average">90</span> sur <span class="best">100</span> </span> basée sur <span class="count">35</span> votes. </span> Comme vous pouvez le constater, les microformats n’utilisent pas d’attribut ou de syntaxe trop complexe, seulement des valeurs de classe bien précises. Vous trouverez un bon nombre de données et d’outils sur le site microformats.org qui a proposé une tentative de codification des pratiques courantes. Microformats.org a ainsi pu réunir un certain nombre de “profils” XMPD que vous trouverez directement sur le wiki microformats. En plus de simples valeurs de classe, microformat c’est également l’utilisation de l’attribut rel, c’est le format hCard, le format hCalendar, etc... LES MICROFORMATS
  • 28. Les microdonnées : Les microdonnées sont représentées par l’arrivée de nouveaux attributs en HTML5. Il est alors possible de donner la référence du document utilisé pour baliser l’information directement au sein de l’élément porteur de ces informations. Il faut attirer l'attention sur l’arrivée d’un document qui tend à devenir une nouvelle référence pour structurer des données : issu d’un consortium entre Google, Bing, Yahoo et Yandex, cette référence est nommée schema.org. Ce sont d’ailleurs les schémas proposés par schema.org. LES MICROFORMATS
  • 29. Nouveaux attributs : Il n’en existe pas énormément : ● itemscope : il permet de créer un item dont le type peut-être précisé grâce à l’attribut suivant, ● itemtype : couplé à itemscope, il accueille une URL vers la référence du schéma (ex : “http://schema.org/Review”) qui devra respecter les valeurs de ce schéma, ● itemprop : il est porteur d’une valeur permettant de préciser la nature d’une donnée au sein d’un schéma spécifié précédemment. ● itemref : il permet de faire le lien complémentaire entre deux données sans descendance. ● itemid : lorsque l’item possède une référence globale unique, comme par exemple un l’identifiant d’un livre (urn:isbn:0-xxx-xxxxx-x). Il est attribué en même temps que l’attribut itemscope. Ces attributs peuvent être transportés par n’importe quel élément (souvent des span pour injecter une donnée sans mise en forme particulière), bien que certaines exceptions, évidentes, existent. Exemple d’une simple revue : <span itemscope itemtype="http://schema.org/Review"> <span itemprop="itemReviewed">Juiz Smart Mobile Admin</span> <span itemprop="reviewRating"> Note de : 90 sur 100 </span> basée sur 35 votes. </span> Rendu : “Juiz Smart Mobile Admin Note de : 90 sur 100 basée sur 35 votes.” LES MICROFORMATS
  • 30. Exemple d’une notation imbriquée dans une revue : Aussi appelée Embedded Items, l’imbrication de différents types de schéma peut intervenir dans le cas de notre exemple de revue. En effet, notre exemple précédent manque quelque peu de précision, puisque schema.org prévoit également un type de schéma pour les évaluations : <div itemscope itemtype="http://schema.org/Review"> <h1 itemprop="itemReviewed">Juiz Smart Mobile Admin</h1> <!-- Imbrication d’un item --> <p itemprop="reviewRating" itemscope itemtype="http://schema.org/AggregateRating"> Note de : <span itemprop="ratingValue">90</span> sur <span itemprop="bestRating">100</span> basée sur <span itemprop="ratingCount">35</span> votes. </p> <!-- / fin de l’imbrication --> <p itemprop="reviewBody"> Ce plugin proposé pour optimiser l'interface d'administration de[…] </p> </div> Rendu : “Juiz Smart Mobile Admin Note de : 90 sur 100 basée sur 35 votes. Ce plugin proposé pour optimiser l’interface d’administration de[…]” LES MICROFORMATS
  • 31. Création d’une fiche « film » : Je prends volontairement ce dernier exemple pour vous présenter une technique qui permet d’associer des informations sans qu’elles soient forcément imbriquées. En effet il arrive que la mise en page d’un site web ou l’évolution de ses informations ne permette pas d’imbriquer les items comme nous l’avons vu juste avant. La fiche film est divisée en deux mais ses informations sont réunies sous le même item grâce à la propriété itemref qui fait référence à l’élément aside#more-info à travers son identifiant “more-info”. LES MICROFORMATS
  • 32. Cet attribut permet de présenter un même item découpé en plusieur éléments à travers la page. Si les informations de notre item Movie avaient été disséminées dans d’autres éléments de la page, il aurait été possible de les cibler grâce à la valeur de leur attribut id de la sorte : <article itemscope itemtype="http://schema.org/Movie" itemref="more-info id2 id3 id4"> Je ne vous ai pas encore expliqué la présence des éléments meta dans la page. Ceux-ci permettent d’insérer une information qui a souvent besoin d’un formatage précis qui est peu intelligible par une personne non aguerrie. Prenons l’exemple de l’information “duration” qui représente la durée. Cette information doit être formatée en respectant le format ISO 8601 qui définit un format de date ou de temps. Dans notre fiche, il aurait été possible d’écrire : <dd itemprop="duration">PT91M</dd> Mais vous imaginez bien ici que PT91M est quelque peu dérangeant pour définir une durée d’une heure et demi. C’est pourquoi, par convention – et si ce n’en est pas encore une il faudrait que ça le devienne – l’information s’écrit dans un élément meta et à côté de l’information intelligible. LES MICROFORMATS
  • 33. Le code HTML correspondant à cette mise en page pourrait ressembler à cela : <section role="main"> <article itemscope itemtype="http://schema.org/Movie" itemref="more-info"> <h1 itemprop="name">Nom du film de la fiche</h1> <img itemprop="image" src="img/the-film.png" alt="" width="150" height="150"> <section itemprop="video" itemscope itemtype="http://schema.org/VideoObject"> <h2>Trailer : <span itemprop="name">Nom du film de la fiche</span></h2> <meta itemprop="duration" content="T1M33S"> <meta itemprop="thumbnail" content="image-miniature-du-trailer.jpg"> <object …> <param …> <embed type="application/x-shockwave-flash" …> </object> <p itemprop="description">Courte description de la vidéo</p> </section> <section itemprop="description"> <p>Contenu principal de ma fiche film</p> </section> <footer> <dl> <dt>Réalisateur</dt> <dd itemprop="director">Emily Atef</dd> <dt>Acteurs</dt> <dd itemprop="actors">Maria-Victoria Dragus</dd> <dd itemprop="actors">Roeland Wiesnekker</dd> <dd itemprop="actors">Wolfram Koch</dd> LES MICROFORMATS
  • 34. <dd itemprop="actors">Christine Citti</dd> <dd itemprop="actors">Nathalie Boutefeu</dd> <dt>Distributeur</dt> <dd itemprop="provider">Les Films du Losange</dd> <dt>Musique par</dt> <dd itemprop="musicBy">John Smith</dd> <dt>Ratio d'image</dt> <dd>2.35</dd> </dl> </footer> </article> <aside id="more-info"> <dl> <dt>Langues</dt> <dd><meta itemprop="inLanguage" content="fr">Français</dd> <dd><meta itemprop="inLanguage" content="de">Allemand</dd> <dt>Année de production</dt> <dd><time datetime="2011" itemprop="dateCreated">2011</time></dd> <dt>Date de sortie</dt> <dd><time datetime="2011-04-25" itemprop="datePublished">25 avril 2012</time></dd> <dt>Genre</dt> <dd itemprop="genre">Drame</dd> <dt>Durée</dt> <dd><meta itemprop="duration" content="PT91M">91 min</dd> </dl> </aside> </section> LES MICROFORMATS
  • 35. LES MICROFORMATS ● Liens : – http://microformats.org/wiki/html5 – http://html5doctor.com/microformats/ – http://speckyboy.com/2011/01/24/beginners-study-guide-to-html5- – http://www.alsacreations.com/tuto/lire/1224-microformats-html5-m
  • 37. L'élément <video>, cousin de <audio> offre en HTML5 une solution simple, native pour les navigateurs pour l'intégration d'une vidéo dans une page web. Elle permet également de proposer une alternative à l'utilisation de Flash pour les plate-formes ne le supportant pas (iOS par exemple avec iPhone, iPod, iPad...). La syntaxe de base de la balise video est extrêmement simple : <video controls src="video.ogv">Ici la description alternative</video> L'attribut src définit bien entendu l'adresse du fichier vidéo, tout comme pour la balise img lorsqu'il s'agit d'une image. Si vous indiquez les dimensions avec les attributs height et width, c'est encore mieux, et si tout va bien, un élément devrait s'afficher dans le navigateur... pour peu que celui-ci supporte le format de vidéo indiqué dans la source. AUDIO & VIDEO
  • 38. On peut également proposer plusieurs sources dans plusieurs formats différents en indiquant les types MIME grâce à l'attribut type : <video width="400" height="222" controls="controls"> <source src="video.mp4" type="video/mp4" /> <source src="video.webm" type="video/webm" /> <source src="video.ogv" type="video/ogg" /> Ici l'alternative à la vidéo : un lien de téléchargement, un message, etc. </video> Les navigateurs ne pouvant pas lire le MP4/H.264 ni la version WebM nativement (comme Firefox 3.6 par exemple) prendront la version au format Ogg Theora. Cela vous oblige néanmoins à encoder le fichier avec différents codecs. Particularité de la syntaxe XHTML : il faut ajouter controls="controls" (et pas juste controls comme vous pourrez le voir sur le premier exemple) pour afficher les possibilités de contrôle de la vidéo. Ceci est valable pour tous les attributs (autoplay, etc.). AUDIO & VIDEO
  • 39. ● Attributs : L'attribut controls donne accès aux contrôles de lecture (boutons de navigation, volume, etc, selon les possibilités du navigateur), ou les masque s'il est omis. L'attribut preload="auto" permet de de spécifier au navigateur de débuter le téléchargement de la vidéo tout de suite, en anticipant sur le fait que l'utilisateur lira la vidéo. Attention, cette option est à manier avec prudence (il est préférable que ce soit la seule raison d'être de la page). Note : il s'agit de l'ancien attribut autobuffer qu'il vous faudra laisser pour Firefox 3.5 et 3.6. L'attribut autoplay="true" comme son nom l'indique, permet de lancer la lecture automatiquement. Cela peut également être problématique avec une connexion à faible bande passante ou sur un terminal mobile. De manière générale, évitez d'imposer vos choix à l'utilisateur... et à sa connexion internet. L'attribut poster="image.jpg" permet d'indiquer une image à afficher par défaut dans l'espace réservé par la vidéo, avant que la lecture de celle-ci ne soit lancée. L'attribut loop indique que la lecture doit s'effectuer en boucle. ● Prérequis : Pensez également à préciser les types MIME dans un fichier .htaccess pour être sûr qu'ils soient corrects, les trois lignes suivantes suffisent à s'assurer la tranquilité : AddType video/ogg .ogv AddType video/mp4 .mp4 AddType video/webm .webm AUDIO & VIDEO
  • 40. ● Formats : Plusieurs formats tiennent le devant de la scène : WebM, MP4 et Ogg Theora. Même si le but de ce tutoriel est de proposer une solution d'intégration de la balise video compatible sur le plus de navigateurs possible (et pas de discuter du choix des formats dans un interminable débat), faisons quand même une présentation rapide. → H.264/MP4 : H.264 est supporté par le Moving Picture Experts Group. C'est un format non-libre (soumis à brevets) et non-gratuit. Toutefois, il est gratuit dans certaines utilisations (la diffusion gratuite de vidéos par des sites Web par exemple). Les fichiers MP4 utilisant H.264 sont lisibles nativement sur les navigateurs Apple (Safari, Safari Mobile) ainsi que sur Google Chrome. AUDIO & VIDEO
  • 41. → OGG/Theora : Theora est un format de compression vidéo open-source, sans brevets. Ceci donne le droit à tous d'utiliser Theora (à des fins non commerciales tout comme à des fins commerciales) sans devoir payer de redevance au consortium MPEG. OGG/Theora est lisible sur Firefox, Opéra, et Google Chrome. AUDIO & VIDEO
  • 42. AUDIO & VIDEO → WebM/VP8 : WebM est un format multimédia ouvert qui a été lancé par Google (après rachat de la société On2 Technologies). L'utilisation est en libre et gratuite. Comme on peut le constater, il y a une grande disparité dans le support des codecs, chacun défendant ses intérêts pour le meilleur ou pour le pire (commerciaux ou libres).
  • 43. AUDIO & VIDEO ● Liens : – http://diveintohtml5.info/video.html – http://fr.wikipedia.org/wiki/Theora – http://www.videojs.com/ –
  • 45. Introduit à l'origine par Apple pour être utilisé dans WebKit pour des logiciels comme Dashboard et le navigateur Safari, canvas a été par la suite adopté par les navigateurs utilisant Gecko (notamment Mozilla Firefox) et Opera, avant d'être standardisé par le groupe de travail WHATWG. Novell a développé une extension activant les XForms dans Internet Explorer1 offrant ainsi une prise en charge des fonctionnalités de canvas. <canvas id="mon_canvas" width="350" height="350"> Texte alternatif pour les navigateurs ne supportant pas Canvas. </canvas> À partir de ce moment, tout se passe du côté de JavaScript, qui va se servir de cet élément HTML pour accéder à la surface de dessin. Pour ceci, deux fonctions sont appelées : getElementById() qui va permettre d'aller chercher et cibler l'élément <canvas> identifié par son attribut id unique (ici mon_canvas),puis la méthode getContext() de l'élément ainsi récupéré pour savoir dans quel contexte de dessin (2D ou 3D) le script va pouvoir agir, et de quelles fonctions il pourra disposer. Le contexte sera l'élément central de gestion de Canvas. <script type="text/javascript"> var c = document.getElementById("mon_canvas"); var ctx = c.getContext("2d"); // Dessine un rectangle rouge ctx.fillStyle = 'red'; ctx.fillRect(30, 30, 50, 50); </script> Canvas
  • 46. Tous les exemples suivants dans ce tutoriel feront appel à cette structure (élément Canvas + élément script + appel à getElementById + getContext) qui ne sera pas reprécisée à chaque fois. Après cette étape préliminaire de mise en place, il faut se plonger dans l'ensemble des méthodes de dessin 2D. Celles-ci vont toutes exploiter le même système de coordonnées : ● Le point de référence (0,0) est situé en haut à gauche ; ● L'axe horizontal (x) est défini par la première coordonnée ; ● L'axe vertical (y) est défini par la seconde coordonnée ; ● Ces valeurs correspondent à la grille entourant les pixels, et non pas aux pixels eux- mêmes. Par exemple le point de coordonnées (4,2) sera situé 4 pixels à droite du coin supérieur gauche, et 2 pixels en-dessous. Canvas Si l'on trace un polygone entre les 3 points présents sur ce schéma, on obtiendra un triangle.
  • 47. Pour commencer, voici un exemple simple qui dessine deux rectangles ayant une intersection, l'un d'entre-eux possédant une transparence alpha : <html> <head> <script type="application/x-javascript"> function draw() { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(200,0,0)"; ctx.fillRect (10, 10, 55, 50); ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; ctx.fillRect (30, 30, 55, 50); } </script> </head> <body onload="draw()"> <canvas id="canvas" width="300" height="300"></canvas> </body> </html> La fonction draw récupère l'élément canvas, et ensuite son contexte 2d. L'objet ctx peut ensuite être utilisé pour dessiner réellement vers le canevas. L'exemple remplit simplement les deux rectangles, en positionnant fillStyle à deux couleurs différentes à l'aide des spécifications de couleur CSS et d'un appel à fillRect. Le second appel à fillStyle utilise rgba() pour spécifier une valeur alpha parmi les informations de couleur. Les appels à fillRect, strokeRect et clearRect affichent un rectangle plein, surligné ou vide. Pour afficher des formes plus complexes, on utilise des chemins. Canvas
  • 48. La fonction beginPath commence un nouveau chemin, et moveTo, lineTo, arcTo, arc et des méthodes similaires sont utilisées pour ajouter des segments au chemin. Le chemin peut être fermé à l'aide de closePath. Une fois que le chemin est créé, vous pouvez utiliser fill ou stroke pour afficher celui-ci sur le canevas. <html> <head> <script type="application/x-javascript"> function draw() { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.fillStyle = "red"; ctx.beginPath(); ctx.moveTo(30, 30); ctx.lineTo(150, 150); ctx.bezierCurveTo(60, 70, 60, 70, 70, 150); ctx.lineTo(30, 30); ctx.fill(); } </script> </head> <body onload="draw()"> <canvas id="canvas" width="300" height="300"></canvas> </body> </html> L'appel à fill() ou stroke() provoque l'utilisation du chemin. Pour être rempli ou dessiné à nouveau, le chemin devra être recréé. Canvas
  • 50. Canvas ● Liens : – http://www.html5canvastutorials.com/ – http://www.lafermeduweb.net/tutorial/l-element-html-5-canvas-p2 – http://en.wikipedia.org/wiki/Canvas_element – http://www.w3schools.com/html/html5_canvas.asp – http://www.whatwg.org/specs/web-apps/current-work/#dynamic – https://developer.mozilla.org/fr/docs/Web/HTML/Canvas?redirect – http://modern-carpentry.com/workshop/html5/waveform/ – http://www.crazyws.fr/dev/20-canvas-html5-pour-vous-inspirer-8I
  • 52. Une des nouveautés introduites par HTML5 est la géolocalisation utilisable via une API d'un navigateur. Cela permet aux pages web d'interroger le navigateur sur la position géographique de l'utilisateur. L'API de base permet d'obtenir les coordonnées en latitude et en longitude ainsi que l'altitude. Celles-ci peuvent alors être exploitées par le biais d'une carte (de type Google Map). Détection du support : if (navigator.geolocation) { //le navigateur supporte la géolocalisation //suite du code ici } else { alert('Votre navigateur ne supporte pas la géolocalisation HTML5'); } Géolocalisation
  • 53. Détail de la méthode getCurrentPosition() : PropertyProperty DescriptionDescription coords.latitude The latitude as a decimal number coords.longitude The longitude as a decimal number coords.accuracy The accuracy of position coords.altitude The altitude in meters above the mean sea level coords.altitudeAccuracy The altitude accuracy of position coords.heading The heading as degrees clockwise from North coords.speed The speed in meters per second timestamp The date/time of the response Géolocalisation
  • 54. Exemple de code pour un client : <script> var x = document.getElementById("demoLoc"); function getLocation() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition); } else{ x.innerHTML="Geolocation is not supported by this browser.";} } function showPosition(position) { x.innerHTML="Latitude:"+position.coords.latitude + "<br>Longitude: " + position.coords.longitude; } </script> Géolocalisation
  • 55. Gestion des erreurs : function showError(error) { switch(error.code) { case error.PERMISSION_DENIED: x.innerHTML="User denied the request for Geolocation." break; case error.POSITION_UNAVAILABLE: x.innerHTML="Location information is unavailable." break; case error.TIMEOUT: x.innerHTML="The request to get user location timed out." break; case error.UNKNOWN_ERROR: x.innerHTML="An unknown error occurred." break; } } Code d'erreurs : ● Permission denied : l'utilisateur n'est pas autorisé pour utiliser la géolocalisation ● Position unavailable : géolocalisation impossible ● Timeout : timeout pour aller jusqu'au bout de la géolocalisation Géolocalisation
  • 56. Example d'affichage de la position sur une carte : function showPosition(position) { var latlon = position.coords.latitude+","+position.coords.longitude; var img_url = "http://maps.googleapis.com/maps/api/staticmap?center=" +latlon+"&zoom=14&size=400x300&sensor=false"; document.getElementById("mapholder").innerHTML="<img src='" + img_url + "'>"; } Géolocalisation
  • 57. Autre méthodes : ● watchPosition() : retourne la position courante ainsi que le mouvement via une icône (voiture). ● clearWatch() : arrête la méthode watchPosition Example d'utilisation de la méthode watchPosition : <script> var x = document.getElementById("demo"); function getLocation() { if (navigator.geolocation) { navigator.geolocation.watchPosition(showPosition); } else { x.innerHTML="Geolocation is not supported by this browser."; } } function showPosition(position) { x.innerHTML="Latitude: " + position.coords.latitude + "<br>Longitude: " + position.coords.longitude; } </script> Géolocalisation
  • 58. Géolocalisation ● Liens : – http://www.w3schools.com/html/tryit.asp?filename=tryhtml5_geo – http://dev.w3.org/geo/api/spec-source.html – http://www.html5-css3.fr/html5/tutoriel-geolocalisation-html5 – http://debray-jerome.developpez.com/articles/l-api-geolocalisation – http://html5demos.com/geo – http://html5professor.com/tutoriels-6.html –
  • 60. L'API offerte aux navigateur web pour gérer les fichiers permet: ● De gérer une liste de fichiers (1:n) sélectionnable depuis la balise <input type="file"> ● Gestion de fichiers raw de type binaires avec autorisations d'accès d'une zone d'octets ● Une interface détaillant le nom du(des) fichier(s), leur type et leur URL ● Une interface permettant de lire un fichier ● Une gestion d'exception permettant la gestion des exceptions Gérer les fichiers
  • 61. Vérifier le support disponible : if (window.File && window.FileReader && window.FileList && window.Blob) { // Accès possible } else { alert('The File APIs are not fully supported in this browser.'); } Création d'un handle sur un fichier : // Récupère le path + nom du fichier var file = document.forms['uploadData']['fileChooser'].files[0]; // Autre moyen de récupérer le path + nom du fichier // var file = document.forms['uploadData']['fileChooser'].files.item(0); if (file) // ou if (file != undefined) { // Traitements sur le fichier . . . } Gérer les fichiers
  • 62. Soit le code HTML suivant : <input type="file" id="files" name="files[]" multiple /> <output id="list"></output> Voici un exemple de code gérant les fichiers : <script> function handleFileSelect(evt) { var files = evt.target.files; // files is a FileList of File objects. List some properties. var output = []; for (var i = 0, f; f = files[i]; i++) { output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ', f.size, ' bytes, last modified: ', f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a', '</li>'); } document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>'; } document.getElementById('files').addEventListener('change', handleFileSelect, false); </script> Gérer les fichiers Création d'un handle sur un fichier : // Récupère le path + nom du fichier var file = document.forms['uploadData']['fileChooser'].files[0]; // Autre moyen de récupérer le path + nom du fichier // var file = document.forms['uploadData']['fileChooser'].files.item(0); if (file) // ou if (file != undefined) { // Traitements sur le fichier . . . }
  • 63. Soit le code HTML suivant : <div id="drop_zone">Drop files here</div> <output id="list"></output> Voici un exemple de code gérant les fichiers déposé en drag/drop : <script> function handleFileSelect(evt) { evt.stopPropagation(); evt.preventDefault(); var files = evt.dataTransfer.files; var output = []; for (var i = 0, f; f = files[i]; i++) { output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ', f.size, ' bytes, last modified: ', f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a', '</li>'); } document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>'; } Gérer les fichiers
  • 64. (...) function handleDragOver(evt) { evt.stopPropagation(); evt.preventDefault(); evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. } // Setup the dnd listeners. var dropZone = document.getElementById('drop_zone'); dropZone.addEventListener('dragover', handleDragOver, false); dropZone.addEventListener('drop', handleFileSelect, false); </script> Gérer les fichiers
  • 65. A aprtir du code html & css suivant : <style> .thumb { height: 75px; border: 1px solid #000; margin: 10px 5px 0 0; } </style> <input type="file" id="files" name="files[]" multiple /> <output id="list"></output> Le code JS permettant de lire le fichier est le suivant : <script> function handleFileSelect(evt) { var files = evt.target.files; // FileList object for (var i = 0, f; f = files[i]; i++) { if (!f.type.match('image.*')) { continue; } var reader = new FileReader(); Gérer les fichiers
  • 66. (...) reader.onload = (function(theFile) { return function(e) { var span = document.createElement('span'); span.innerHTML = ['<img class="thumb" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join(''); document.getElementById('list').insertBefore(span, null); }; })(f); reader.readAsDataURL(f); } } document.getElementById('files').addEventListener('change', handleFileSelect, false); </script> Gérer les fichiers
  • 67. A partir du code html suivant : <style> #byte_content { margin: 5px 0; max-height: 100px; overflow-y: auto; overflow-x: hidden; } #byte_range { margin-top: 5px; } </style> <input type="file" id="files" name="file" /> Read bytes: <span class="readBytesButtons"> <button data-startbyte="0" data-endbyte="4">1-5</button> <button data-startbyte="5" data-endbyte="14">6-15</button> <button data-startbyte="6" data-endbyte="7">7-8</button> <button>entire file</button> </span> <div id="byte_range"></div> <div id="byte_content"></div> Gérer les fichiers
  • 68. Le code Javascript permettant de télécharger un fichier binaire est le suivant : <script> function readBlob(opt_startByte, opt_stopByte) { var files = document.getElementById('files').files; if (!files.length) { alert('Please select a file!'); return; } var file = files[0]; var start = parseInt(opt_startByte) || 0; var stop = parseInt(opt_stopByte) || file.size - 1; var reader = new FileReader(); reader.onloadend = function(evt) { if (evt.target.readyState == FileReader.DONE) { // DONE == 2 document.getElementById('byte_content').textContent = evt.target.result; document.getElementById('byte_range').textContent = ['Read bytes: ', start + 1, ' - ', stop + 1, ' of ', file.size, ' byte file'].join(''); } }; var blob = file.slice(start, stop + 1); reader.readAsBinaryString(blob); } Gérer les fichiers
  • 69. (...) document.querySelector('.readBytesButtons').addEventListener('click', function(evt) { if (evt.target.tagName.toLowerCase() == 'button') { var startByte = evt.target.getAttribute('data-startbyte'); var endByte = evt.target.getAttribute('data-endbyte'); readBlob(startByte, endByte); } }, false); </script> Gérer les fichiers
  • 70. A partir du code html suivant : <style> #progress_bar { margin: 10px 0; padding: 3px; border: 1px solid #000; font-size: 14px; clear: both; opacity: 0; -moz-transition: opacity 1s linear; -o-transition: opacity 1s linear; -webkit-transition: opacity 1s linear; } #progress_bar.loading { opacity: 1.0; } #progress_bar .percent { background-color: #99ccff; height: auto; width: 0; } </style> Gérer les fichiers
  • 71. <input type="file" id="files" name="file" /> <button onclick="abortRead();">Cancel read</button> <div id="progress_bar"><div class="percent">0%</div></div> Le code Javascript permettant de monitorer la progression de la lecture d'un fichier est le suivant : <script> var reader; var progress = document.querySelector('.percent'); function abortRead() { reader.abort(); } function errorHandler(evt) { switch(evt.target.error.code) { case evt.target.error.NOT_FOUND_ERR: alert('File Not Found!'); break; case evt.target.error.NOT_READABLE_ERR: alert('File is not readable'); break; case evt.target.error.ABORT_ERR: break; // noop default: alert('An error occurred reading this file.'); }; } Gérer les fichiers
  • 72. (...) function updateProgress(evt) { // evt is an ProgressEvent. if (evt.lengthComputable) { var percentLoaded = Math.round((evt.loaded / evt.total) * 100); // Increase the progress bar length. if (percentLoaded < 100) { progress.style.width = percentLoaded + '%'; progress.textContent = percentLoaded + '%'; } } } function handleFileSelect(evt) { // Reset progress indicator on new file selection. progress.style.width = '0%'; progress.textContent = '0%'; reader = new FileReader(); reader.onerror = errorHandler; reader.onprogress = updateProgress; reader.onabort = function(e) { alert('File read cancelled'); }; reader.onloadstart = function(e) { document.getElementById('progress_bar').className = 'loading'; }; Gérer les fichiers
  • 73. (...) reader.onload = function(e) { // Ensure that the progress bar displays 100% at the end. progress.style.width = '100%'; progress.textContent = '100%'; setTimeout("document.getElementById('progress_bar').className='';", 2000); } // Read in the image file as a binary string. reader.readAsBinaryString(evt.target.files[0]); } document.getElementById('files').addEventListener('change', handleFileSelect, false); </script> Gérer les fichiers
  • 74. Autre exemple : var file = document.getElementById('file').files[0]; if (file) { // create an identical copy of file // the two calls below are equivalent var fileClone = file.slice(); var fileClone2 = file.slice(0, file.size); var fileChunkFromEnd = file.slice(-(Math.round(file.size/2))); var fileChunkFromStart = file.slice(0, Math.round(file.size/2)); // slice file from beginning till 150 bytes before end var fileNoMetadata = file.slice(0, -150, "application/experimental"); } Gérer les fichiers
  • 75. Création d'un objet blob (Binary Large Object) : var a = new Blob(); // Creation d'un tableau de 10.24 octets var buffer = new ArrayBuffer(1024); var shorts = new Uint16Array(buffer, 512, 128); var bytes = new Uint8Array(buffer, shorts.byteOffset + shorts.byteLength); var b = new Blob([toNativeLineEndings("foobarbazetcetc" + "birdiebirdieboo")], {type: "text/plain;charset=UTF-8"}); var c = new Blob([b, shorts]); var a = new Blob([b, c, bytes]); var d = new Blob([buffer, b, c, bytes]); Gérer les fichiers
  • 76. Gérer les fichiers ● Liens : – http://www.html5rocks.com/en/tutorials/file/dndfiles/ – http://en.wikipedia.org/wiki/File_select – http://www.html5rocks.com/en/tutorials/file/filesystem/?redirect_f – http://dailyjs.com/2009/11/30/html5-file-api/ – http://dret.typepad.com/dretblog/2010/04/html5-file-writer-api.htm – https://developer.mozilla.org/en-US/docs/Using_files_from_web_a – http://dev.w3.org/2006/webapi/FileAPI/ – http://www.filosophy.org/post/27/a_state_of_limbo_the_html5_fil
  • 78. Créer un élément pouvant être déplacé : Pour rendre un élément déplaçable, il suffit de lui ajouter l'attribut «draggable » à true: <img id="drag1" src="img_logo.gif" draggable="true" ondragstart="drag(event)" width="336" height="69"> L'attribut draggable positionné à True permet donc d'activer le drag & drop vis à vis de l'image avec l'id « drag1 ». Drag & drop
  • 79. Créer un élément conteneur pouvant reçevoir un élément à déplacer: Pour définir un conteneur, il faut définir 2 callbacks sur les évènements ondrop et ondragover : <div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div> Il faudra définir dans le HEAD de la page un style pour le div : <style type="text/css"> #div1 { width:350px;height:70px;padding:10px;border:1px solid #aaaaaa; } </style> Les dimensions sont compatible avec les dimensions de l'image pouvant être déplacer dans le div. Drag & drop
  • 80. Exemple d'implémentation des callbacks de gestion des évenements ondrop et ondragover : <script> function allowDrop(ev) { ev.preventDefault(); } function drag(ev) { ev.dataTransfer.setData("Text",ev.target.id); } function drop(ev) { ev.preventDefault(); var data = ev.dataTransfer.getData("Text"); ev.target.appendChild(document.getElementById(data)); } </script> Drag & drop
  • 81. Drag & drop ● Liens : – http://html5demos.com/drag – http://html5demo.braincracking.org/demo/dragNDrop.php – http://www.startyourdev.com/codes/code-drag-drop.php – http://chez-syl.fr/2012/03/drag-and-drop-html5-jquery/ – http://www.html5rocks.com/en/tutorials/dnd/basics/
  • 83. Une des raisons pour lesquels les SSE ont été maintenus dans l'ombre, c'est que des API comme les Web Sockets fournissaient déjà un protocole riche et bi- directionnel en duplex intégral. Avoir un canal bidirectionnel est plus attrayant pour des choses comme des jeux, des applications de messagerie, et pour le cas où vous avez besoin à proximité de mises à jour en temps réel dans les deux sens. Toutefois, dans certains scénarios de données n'a pas besoin d'être envoyé par le client. Vous devez simplement mises à jour de certaines mesures du serveur. Quelques exemples seraient état des mises à jour amis, cours de la Bourse, les fils​​ de nouvelles, ou d'autres mécanismes d'incitation automatisée de données (par exemple, mettre à jour une base de données SQL Web côté client ou un magasin d'objets IndexedDB). Si vous avez besoin d'envoyer des données à un serveur, l'objet XMLHttpRequest est utile. Push server PUSH mono-directionnel
  • 84. Les SSE sont envoyés via du HTTP1.1 traditionnel. Cela signifie qu'ils n'ont pas besoin d'un protocole spécifique ou la mise en œuvre de serveur pour obtenir de travail. Les Web Sockets d'autre part, nécessitent des connexions en duplex intégral et des serveurs de sockets Web dédiés pour gérer ce protocole. En outre, les Server-Sent Events ont une variété de caractéristiques qui manque aux Web sockets tel que : ● la reconnexion automatique ; ● les événements associés à un ID ; ● la possibilité d'envoyer des événements arbitraires Push server
  • 85. Exemple d'enregistrement sur un flux d'évènements serveur : Cela revient à instancier un objet EventSource avec l'url du flux : if (!!window.EventSource) { var source = new EventSource('stream.php'); } else { // Result to xhr polling } Push server
  • 86. Ensuite, il faut déclarer un handle de message pour chaque événement : source.addEventListener('message', function(e) { console.log(e.data); }, false); source.addEventListener('open', function(e) { // Connection was opened. }, false); source.addEventListener('error', function(e) { if (e.readyState == EventSource.CLOSED) { // Connection was closed. } }, false); Push server
  • 87. Il est possible que le serveur envoie des données complexes sous format json : data: {n data: "msg": "hello world",n data: "id": 12345n data: }nn Pour ce faire, un handle de message sera rajouté et le message sera parsé pour reformer l'objet au format de type json : source.addEventListener('message', function(e) { var data = JSON.parse(e.data); console.log(data.id, data.msg); }, false); Le JSON (JavaScript Object Notation) peut et doit être vu comme une structure de Données, ou le résultat d'une sérialiation d'objet. Push server
  • 88. Pour des messages plus complexes : data: {"msg": "First message"}nn event: userlogonn data: {"username": "John123"}nn event: updaten data: {"username": "John123", "emotion": "happy"}nn Le traitement sera le suivant : source.addEventListener('message', function(e) { var data = JSON.parse(e.data); console.log(data.msg); }, false); source.addEventListener('userlogon', function(e) { var data = JSON.parse(e.data); console.log('User login:' + data.username); }, false); source.addEventListener('update', function(e) { var data = JSON.parse(e.data); console.log(data.username + ' is now ' + data.emotion); }, false); Push server
  • 89. Coté serveur une implémentation en PHP est la suivante : <?php header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); // recommended to prevent caching of event data. /** * Constructs the SSE data format and flushes that data to the client. * * @param string $id Timestamp/id of this connection. * @param string $msg Line of text that should be transmitted. */ function sendMsg($id, $msg) { echo "id: $id" . PHP_EOL; echo "data: $msg" . PHP_EOL; echo PHP_EOL; ob_flush(); flush(); } $serverTime = time(); sendMsg($serverTime, 'server time: ' . date("h:i:s", time())); ?> Push server
  • 90. Autre implémentation en Node.js : var http = require('http'); var sys = require('sys'); var fs = require('fs'); http.createServer(function(req, res) { //debugHeaders(req); if (req.headers.accept && req.headers.accept == 'text/event-stream') { if (req.url == '/events') { sendSSE(req, res); } else { res.writeHead(404); res.end(); } } else { res.writeHead(200, {'Content-Type': 'text/html'}); res.write(fs.readFileSync(__dirname + '/sse-node.html')); res.end(); } }).listen(8000); Push server
  • 91. function sendSSE(req, res) { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); var id = (new Date()).toLocaleTimeString(); // Sends a SSE every 5 seconds on a single connection. setInterval(function() { constructSSE(res, id, (new Date()).toLocaleTimeString()); }, 5000); constructSSE(res, id, (new Date()).toLocaleTimeString()); } Push server
  • 92. Le fichier sse-node.html aura le contenu suivant : <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <script> var source = new EventSource('/events'); source.onmessage = function(e) { document.body.innerHTML += e.data + '<br>'; }; </script> </body> </html> Push server
  • 93. Web socket (WS) vs évènements (SSE pour Server-Sent Events) envoyé depuis le serveur : Advantages de SSE opposé aux Web sockets: ● Tranport via http au lieu d'un protocole dédié ; ● Peut être quand même utilisé via un backport sur des navigateurs ne disposant pas du support ; ● Support intégré incluant des re-connexions et event-id ● Portocol simple Advantages des Web sockets opposé aux SSE : ● Communication temps réelle et bi-directionnelle ● Support natif de plusieurs navigateur web Utilisation idéale des SSE : ● Alimentation de données en continue ; ● Mise à jour des données twitter, fb, chat, … ; ● Notification serveur->browser Push server SSE WEB SOCKETS
  • 94. Push server ● Liens : – http://fr.wikipedia.org/wiki/Server_push – http://html5hacks.com/blog/2013/04/21/push-notifications-to-the-b – http://pusher.com/tutorials/html5_realtime_push_notifications – http://www.w3schools.com/html/html5_serversentevents.asp – http://html5-realtime-push-notifications.eu01.aws.af.cm/examples/ – https://github.com/pusher/html5-realtime-push-notifications – http://boedesign.com/blog/2009/07/11/growl-for-jquery-gritter/ – https://github.com/ehynds/jquery-notify – http://www.erichynds.com/blog/a-jquery-ui-growl-ubuntu-notifica – http://www.erichynds.com/examples/jquery-notify/index.htm – http://dev.w3.org/html5/eventsource/
  • 96. 96 Web messaging Architecture : Html5 page Iframe XXX (message)
  • 97. Soit une page web contenant une iframe, on récupère son handle de la façon suivante : var o = document.getElementsByTagName('iframe')[0]; Ensuite on peut lui envoyer un message : o.contentWindow.postMessage('Hello world', 'http://b.example.org/'); Web messaging
  • 98. Web messaging L'iframe pourra traiter le message via la callback suivante : window.addEventListener('message', receiver, false); function receiver(e) { if (e.origin == 'http://example.com') { if (e.data == 'Hello world') { e.source.postMessage('Hello', e.origin); } else { console.log(e.data); } } }
  • 99. Web messaging ● Liens : – http://www.w3.org/TR/webmessaging/ – http://en.wikipedia.org/wiki/Web_Messaging – http://dev.opera.com/articles/view/window-postmessage-messagec – http://msdn.microsoft.com/fr-fr/library/ie/hh781494(v=vs.85).aspx – http://fr.slideshare.net/miketaylr/html5-web-messaging-7970364 – http://fr.slideshare.net/miketaylr/html5-web-messaging-7970364 –
  • 101. Web sockets ● Architecture : 101 Connexion persistante serveurclient database La connexion client/serveur : - permet une communication « temps réel » pour des applications genre chat, cours de bourse, … ; - permet aux serveurs d'envoyer des évènements ; - ouvert à l'initiative du client et reste ouvert par la suite ; - le serveur doit supporter un certain nombre de sockets (1 par client) data
  • 102. Web sockets → Exemple d'application pour un mini-chat : db users
  • 103. Web sockets http://bloga.jp/ws/jq/js/jquery.ws-0.3-noenc-pre.js <script src="./jquery-1.3.2.min.js"></script> <script src="./jquery.ws-0.3pre.js"></script> <input id="msg" type="text" value=""> <button id="send">send</button> <div id="board"></div> <script type="text/javascript"> var wsoj = $.ws.conn( { url : "ws://example.com/mytest", onopen    : function(e) { $("#board").prepend("conected"); }, onmessage : function(msg,wsoj) { $("#board").prepend(msg) }, onclose   : function(e) { $("#board").prepend("closed"); } }); $("#send").click(function() { $(wsoj).wssend($("#msg").val()) }); </script> → Exemple d'implémentation d'un client :
  • 104. Web sockets ● Langages pour le serveur : – Java (ex : jWebsocket, … ) – PHP (ex : phpwebsocket, spoutserver… ) – Ruby – Python (ex : pywebsocket, … ) – C# (ex : Nugget) – Javascript (ex : node.js, … ) 104
  • 105. Web sockets → Exemple de serveur : from mod_pywebsocket import msgutil import thread import getopt import os import sys import time _GOODBYE_MESSAGE = 'Goodbye' file = '/somewhere/test' class tail(): last_mtime = None def __init__(self, filename, delay, sock): self.filename = filename self.delay = delay self.sock = sock def run(self): while True: time.sleep(self.delay) stat = os.stat(self.filename) if stat.st_mtime != self.last_mtime: self.last_mtime = stat.st_mtime self.read() def read(self): try: length = 0 f = open(self.filename, 'r') for line in f: length += 1 f.seek(0) cnt = 0 for line in f: cnt += 1 if cnt == length: msgutil.send_message(self.sock, line[:-1])
  • 106. f.close except Exception: if(f): f.close def web_socket_do_extra_handshake(request): pass # Always accept. def web_socket_transfer_data(request): attr = () thread.start_new_thread(tail(file, 0.5, request).run, attr) while True: try: line = msgutil.receive_message(request) f = open(file, 'a') f.write(line+"") os.fsync(f.fileno()) f.flush() f.close if line == _GOODBYE_MESSAGE: Return except Exception: return Web sockets (suite) Nécessite le module python : http://code.google.com/p/pywebsocket/
  • 107. Web sockets ● Liens : – http://fr.wikipedia.org/wiki/Websocket – http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-06 – http://svn.whatwg.org/webapps/complete.html#websocket – http://www.ape-project.org/ – https://github.com/disconnect/apache-websocket – http://jwebsocket.org/ – http://code.google.com/p/pywebsocket/ – http://blog.kaazing.com/2010/02/17/html5-web-sockets-and-pipeli – http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-68 – http://archive.plugins.jquery.com/project/ws – http://martinsikora.com/nodejs-and-websocket-simple-chat-tutoria – http://dev.w3.org/html5/websockets/
  • 109. Web storage Cookies limités à quelques ko contre quelques Mo pour les storages Ajout de deux interfaces/objets de stockage : → Stockage de session sessionStorage : L'interface sessionStorage mémorise les données sur la durée d'une session de navigation, et sa portée est limitée à la fenêtre ou l'onglet actif. Lors de sa fermeture, les données sont effacées. Contrairement au cookies, il n'y a pas d'interférence. Chaque stockage de session est limité à un domaine → Stockage local localStorage : L'interface localStorage mémorise les données sans limite de durée de vie. Contrairement à sessionStorage, elles ne sont pas effacées lors de la fermeture d'un onglet ou du navigateur. La portée de localStorage est de facto plus large : il est possible de l'exploiter à travers plusieurs onglets ouverts pour le même domaine ou plusieurs fenêtres ; à partir du moment où il s'agit bien sûr du même Navigateur. Il n'y a pas de partage des données Web Storage entre les différents navigateurs qui peuvent être installés sur une même machine.
  • 110. Web storage Usages et précautions Le stockage de données dans le navigateur web se prête à différentes applications, particulièrement lorsqu'il s'agit d'exécuter des traitements sans faire intervenir le serveur, ou lorsqu'il faut mémoriser facilement de petites quantités de données pour l'utilisateur pour les faire persister durant sa navigation. Parmi ces avantages : ● stocker rapidement des données en cache sans faire intervenir le serveur (par exemple via AJAX), ● augmenter la performance ressentie et faciliter les développements, ● se passer des cookies et du trafic HTTP supplémentaire qu'ils représentent (un cookie est envoyé à chaque requête effectuée sur un domaine), ● exploiter un espace alloué plus important que la limite imposée par les cookies (fixée à 4 Ko), ● retrouver des données immédiatement à la reconnexion ou les mémoriser pour éviter la perte s'il y a déconnexion. Attention : les données ne sont pas cryptées, accessibles facilement à tout utilisateur ayant accès au navigateur, et modifiables de la même façon. Il ne faut donc pas y placer d'informations sensibles. Pour ces raisons et d'autres, certains navigateurs exigent de consulter la page appelant le stockage via un domaine, (c'est-à-dire avec une url en http://, que ce soit localhost ou bien un nom de domaine complet) et non pas en fichier local (adresse file://). Sinon, une exception de sécurité peut être déclenchée. Ceci peut sembler logique car les données sont en théorie attachées à un domaine.
  • 111. Web storage Hormis les spécificités concernant la persistance des données, les méthodes d'accès sont communes : ● setItem(clé,valeur) : stocke une paire clé/valeur ● getItem(clé) : retourne la valeur associée à une clé ● removeItem(clé) : supprime la paire clé/valeur en indiquant le nom de la clé ● key(index): retourne la clé stockée à l'index spécifié ● clear(): efface toutes les paires Pour agrémenter le tout, la propriété .length renvoie le nombre de paires stockées. La console Javascript des navigateurs est un outil essentiel pour tester et vérifier le bon fonctionnement de Web Storage. Accès aux données : Note : Les exemples suivants se basent sur sessionStorage mais fonctionneront de la même façon avec localStorage.
  • 112. Web storage Stockage : sessionStorage.setItem("couleur","vert") Le premier argument de setItem est la clé (toujours de type String). Elle précise l'endroit où sont stockées les données afin de pouvoir les y retrouver ultérieurement. Récupération : var couleur = sessionStorage.getItem("couleur"); Grâce à la clé initialement créée avec setItem il est possible de récupérer facilement les données. Ces dernières sont renvoyées sous la forme d'une chaîne de caractère. Suppression : sessionStorage.removeItem("couleur"); Nous supprimons l'élément de session "couleur". Suppression totale : sessionStorage.clear(); Suppression complète de toutes les valeurs de session. Accès direct : Dans la plupart des situations, les variables seront accessibles directement en tant que membres de l'interface. sessionStorage.couleur = "vert"; console.log(sessionStorage.couleur);
  • 114. Web storage Une première application peut être la mémorisation de champs de formulaire, pour stocker les données entrées par l'utilisateur. Bien que ceci soit applicable à toute variable manipulée en JavaScript. Pour ceci, l'événement change sur <textarea> est sollicité pour stocker la valeur courante de l'élément dans sessionStorage.message : <textarea id="message" name="message" onchange="sessionStorage.message=this.value"></textarea> Notez que cette façon de faire est très compacte mais n'est pas des plus esthétiques car le code JavaScript se retrouve "mélangé" au contenu HTML de la page. Ce script doit être placé en fin de document : <script> // Détection du support du storage if(typeof sessionStorage!='undefined') { // Vérifie si la variable message a été stoquée dans les sessionStorage : if('message' in sessionStorage) { $('textarea#message').text() = sessionStorage.getItem('message'); } } else { console.log("sessionStorage n'est pas supporté"); } </script> http://www.codegateway.com/2012/03/get-textarea-value-in-jquery.html Exemple n° 1 :
  • 115. Un deuxième exemple très simple à mettre en place est celui d'un compteur de visites. <p>Vous avez vu cette page <span id="visites"></span> fois</p> Le principe est : ● aller interroger la clé visites dans localStorage dès le chargement du document ● effectuer toutes les vérifications nécessaires (est-ce qu'il y a déjà quelque chose stocké à cet emplacement, peut-on convertir cette chaîne de texte en nombre entier) ● incrémenter le compteur ● le stocker à nouveau au même emplacement pour le conserver ● afficher la valeur à un emplacement dans la page <script> if(typeof localStorage!='undefined') { // Récupération de la valeur dans web storage var nbvisites = localStorage.getItem('visites'); // Vérification de la présence du compteur if(nbvisites!=null) { // Si oui, on convertit en nombre entier la chaîne de texte qui fut stockée nbvisites = parseInt(nbvisites); } else { nbvisites = 1; } // Incrémentation nbvisites++; Exemple n° 2 : Web storage
  • 116. // Stockage à nouveau en attendant la prochaine visite... localStorage.setItem('visites',nbvisites); // Affichage dans la page document.getElementById('visites').innerHTML = nbvisites; } else { alert("localStorage n'est pas supporté"); } </script> Pour l'affichage, cet exemple se sert de l'identifiant id et de la fonction getElementById() pour le cibler, afin d'accéder à sa propriété innerHTML, c'est-à-dire son contenu HTML interne, modifiable. Attention : cette information restera spécifique et locale au visiteur, ne sera pas échangée avec le serveur (hors utilisation d'Ajax par exemple), et donc ne pourra être exploitée pour établir des statistiques générales. Web storage
  • 117. Web storage Utilisation de JSON : Web Storage est bien pratique pour stocker de simples chaînes de texte. Lorsqu'il s'agit de manipuler des données plus complexes, entre autres des objets JavaScript, il faut leslinéariser au préalable en chaînes de texte puisque Web Storage n'accepte que ce type de données. Le format JSON (JavaScript Object Notation) est la solution de prédilection. Deux méthodes équipent les navigateurs modernes : JSON.stringify() qui prend en paramètre un objet et renvoie une chaîne de texte linéarisée, et son inverse JSON.parse() qui reforme un objet à partir de la chaîne linéarisée. Des frameworks populaires tels que jQuery sont équipés de fonctions similaires (parseJSON) pour les anciens navigateurs qui ne seraient pas équipés en natifs de telles méthodes de conversion. Stockage : var monobjet = { propriete1 : "valeur1", propriete2 : "valeur2" }; var monobjet_json = JSON.stringify(monobjet); sessionStorage.setItem("objet",monobjet_json); Lecture : var monobjet_json = sessionStorage.getItem("objet"); var monobjet = JSON.parse(monobjet_json); // Affichage dans la console console.log(monobjet); Dans le cadre de la lisibilité de cette démonstration, cet exemple de code ne fait appel que modestement à JSON, il serait possible de l'exploiter de façon beaucoup plus complexe et évoluée en fonction de la quantité de données à stocker et de leur provenance.
  • 118. Aller plus loin : L'API prévoit aussi des événements storage pour être notifié à chaque changement opéré dans l'espace alloué. Ceux-ci ne sont pas encore très répandus. Pour mettre en place des stockages plus évolués, pour des données binaires ou bien du point de vue de la structure et des opérations de recherche, tri et maintenance, deux approches coexistent : WebSQL dont la spécification est au point mort et qui ne sera pas maintenu à long terme ni intégré à Firefox et Internet Explorer, mais qui a été implémenté par WebKit et Opera. Cette tentative faisait entrer le langage SQL côté client, ce qui était compréhensible pour les développeurs utilisant déjà les bases côté serveur (MySQL, etc) mais n'est pas conforme à l'esprit des différents standards du web : cela nécessiterait de spécifier totalement SQL ou un sous-ensemble tel que SQLite ce qui n'est pas le rôle du W3C. IndexedDB (Indexed Database) revêt une approche totalement orientée vers JavaScript, sans SQL, avec de la manipulation d'objets. Elle est cependant encore peu répandue (IE10 avec préfixe, Chrome et Firefox avec préfixe) ; et demande une phase d'apprentissage supplémentaire même pour les développeurs déjà aguerris avec SQL. Web storage
  • 119. Prise en charge :  Pour les versions d'Internet Explorer antérieures à IE8, il existe une interface nommée userData qui alloue 1 Mo par domaine et qui fonctionne sensiblement de la même manière. Pour l'exploiter, il faudra cependant adapter les fonctions au cas par cas, ou bien passer par un framework unifiant toutes les méthodes d'appel en fonction du stockage disponible.
  • 120. Web sockets ● Liens : – http://dev.opera.com/articles/view/web-storage/ – https://developers.google.com/web-toolkit/doc/latest/DevGuideHtm – https://developer.mozilla.org/en-US/docs/Web/Guide/DOM/Storag – http://msdn.microsoft.com/en-us/library/cc197062(VS.85).aspx#_d – http://theburningmonk.com/2010/12/having-fun-with-html5-local- – http://diveintohtml5.info/detect.html
  • 122. Web sql Ouverture d'une base de données : html5rocks.webdb.db = null; html5rocks.webdb.open = function() { var dbSize = 5 * 1024 * 1024; // 5MB html5rocks.webdb.db = openDatabase("Todo", "1.0", "Todo manager", dbSize); } html5rocks.webdb.onError = function(tx, e) { console.log("There has been an error: " + e.message); } html5rocks.webdb.onSuccess = function(tx, r) { // re-render the data. // loadTodoItems is defined in Step 4a html5rocks.webdb.getAllTodoItems(loadTodoItems); }
  • 123. Web sql Creation d'une table : html5rocks.webdb.createTable = function() { // Récupération du handle de la database var db = html5rocks.webdb.db; db.transaction(function(tx) { tx.executeSql("CREATE TABLE IF NOT EXISTS " + "todo(ID INTEGER PRIMARY KEY ASC, todo TEXT, added_on DATETIME)", []); }); }
  • 124. Web sql Ajout d'une donnée dans une table : html5rocks.webdb.addTodo = function(todoText) { // Récupération du handle de la database var db = html5rocks.webdb.db; db.transaction(function(tx) { var addedOn = new Date(); tx.executeSql("INSERT INTO todo(todo, added_on) VALUES (?,?)", [todoText, addedOn], html5rocks.webdb.onSuccess, html5rocks.webdb.onError); }); }
  • 125. Web sql Sélection d'une donnée dans une table : html5rocks.webdb.getAllTodoItems = function(renderFunc) { // Récupération du handle de la database var db = html5rocks.webdb.db; db.transaction(function(tx) { tx.executeSql("SELECT * FROM todo", [], renderFunc, html5rocks.webdb.onError); }); }
  • 126. Web sql Mise en forme des données issue de la base de données : function loadTodoItems(tx, rs) { var rowOutput = ""; var todoItems = document.getElementById("todoItems"); for (var i=0; i < rs.rows.length; i++) { rowOutput += renderTodo(rs.rows.item(i)); } todoItems.innerHTML = rowOutput; } function renderTodo(row) { return "<li>" + row.todo + " [<a href='javascript:void(0);' onclick='html5rocks.webdb.deleteTodo(" + row.ID +");'>Delete</a>]</li>"; }
  • 127. Web sql Suppression d'une données dans une table : html5rocks.webdb.deleteTodo = function(id) { // Récupération du handle de la database var db = html5rocks.webdb.db; db.transaction(function(tx) { tx.executeSql("DELETE FROM todo WHERE ID=?", [id], html5rocks.webdb.onSuccess, html5rocks.webdb.onError); }); }
  • 128. Web sql Initialisation : .... function init() { html5rocks.webdb.open(); html5rocks.webdb.createTable(); html5rocks.webdb.getAllTodoItems(loadTodoItems); } </script> <body onload="init();">
  • 129. Web sql ● Liens : – http://www.w3.org/TR/webdatabase/ – http://www.w3.org/TR/IndexedDB/ – http://html5sql.com/index.html
  • 131. Web worker Vérification du support : if(typeof(Worker)!=="undefined") { // Yes! Web worker support! // Some code..... } else { // Sorry! No Web Worker support.. }
  • 132. Web worker Création d'un worker fichier « workers.js » : var i=0; function timedCount() { i=i+1; postMessage(i); setTimeout("timedCount()",500); } timedCount();
  • 133. Web worker Création d'un worker objet : if (typeof(w)=="undefined") { w = new Worker("demo_workers.js"); } Il est possible de déclarer un handle de messages associé au worker : w.onmessage=function(event) { document.getElementById("result").innerHTML = event.data; };
  • 134. Web worker Arrêt d'un worker : w.terminate();
  • 135. Exemple complet : <!DOCTYPE html> <html> <body> <p>Count numbers: <output id="result"></output></p> <button onclick="startWorker()">Start Worker</button> <button onclick="stopWorker()">Stop Worker</button> <br><br> <script> var w; function startWorker() { If (typeof(Worker) !== "undefined") { if(typeof(w)=="undefined") { w = new Worker("demo_workers.js"); } w.onmessage = function (event) { document.getElementById("result").innerHTML=event.data; }; } else { document.getElementById("result").innerHTML="Sorry, your browser does not support Web Workers..."; } } function stopWorker() { w.terminate(); } </script> </body> </html>
  • 136. Web worker ● Liens : – https://developer.mozilla.org/en-US/docs/Web/Guide/Performance – http://www.siteduzero.com/informatique/tutoriels/html5-web-work – http://blogs.msdn.com/b/davrous/archive/2011/07/08/introduction- – http://www.w3schools.com/html/html5_webworkers.asp –
  • 138. App. offline L’application cache repose principalement sur l’utilisation d’un fichier “manifest” à ajouter aux pages HTML de votre site. Tout d’abord, créons donc une structure basique de page web : <!DOCTYPE html> <html> <head> <style type="text/css"> #main{ width:900px; margin:auto; } </style> </head> <body> <div id="main"> <h1>Ceci est mon application offline</h1> <img src="earth-folder.png" /> </div> </body> </html>
  • 139. App. offline Afin d’utiliser le cache d’application, il va falloir déclarer un fichier manifest. Ce fichier se déclare dans la balise html comme ceci : <html manifest="site.manifest"> Une fois déclaré, il faut bien sûr créer le fichier manifest en question. Appelons le nôtre “site.manifest”. Dans ce fichier, qui commence obligatoirement par la ligne “CACHE MANIFEST”, nous allons déclarer les fichiers qui doivent être mis en cache : CACHE MANIFEST # Version 0.1 index.html earth-folder.png
  • 140. App. offline On peut également y ajouter des commentaires. Chaque ligne de commentaire doit commencer par #. Il est important de versionner son fichier manifest via un commentaire, afin que le navigateur détecte par la suite les changements dans le fichier. Notons qu’il est possible d’utiliser des URL absolues (http://www.mon-url.com/absolue/fichier.html). Il est possible d’ajouter différentes sections à notre fichier manifest : ● CACHE, il s’agit de la section par défaut qui liste les fichiers à mettre en cache. ● NETWORK, qui liste les fichiers qui nécessitent obligatoirement une connexion internet. ● FALLBACK, qui liste les fichiers qui, au cas où ils ne soient pas accessibles en ligne, doivent renvoyer vers d’autres fichiers. L’exemple suivant représente un site web classique dont la page d’accueil, le CSS et les images sont mises en cache. Si l’utilisateur se connecte à la page d’accueil en étant hors ligne, la page offline.html lui est présentée au lieu d’index.html. Il est donc informé qu’il est déconnecté. Par conséquent il ne pourra pas accéder aux autres pages du site, puisque la section NETWORK spécifie via une étoile “*”, que tous les autres fichiers requièrent une connexion internet. CACHE MANIFEST # v0.1 CACHE: index.html css/style.css img/logo.png FALLBACK: / /offline.html NETWORK: *
  • 141. App. offline Le .htaccess : Nous arrivons maintenant au passage (un peu) délicat. Il va falloir déclarer le MIME-type du fichier manifest. Ceci se fait par l’intermédiaire du fichier de configuration de serveur. Dans la grande majorité des cas vous utiliserez un fichier .htaccess pour les projets PHP. Créez donc un fichier .htaccess dans le répertoire de votre application et ajoutez-y simplement la ligne : AddType text/cache-manifest manifest Dans cette ligne, on déclare que tous les fichiers se terminant par “manifest” ont pour MIME-type “text/cache-manifest”.
  • 142. App. offline Test de l’application hors ligne : Afin de pouvoir tester localement notre application, nous allons devoir passer par Apache (et oui, faites chauffer vos WAMP / MAMP / LAMP !). Plaçons notre application dans le dossier de votre serveur (www pour WAMP) et rendez-vous sur l’adresse http://localhost/ Si tout se passe bien, votre page s’affiche. Maintenant stoppez les services de WAMP, puis rafraîchissez la page. Alors qu’une page classique aurait naturellement fait afficher une belle erreur 404… Votre page est toujours là ! Ouvrez maintenant la console de votre navigateur si celui-ci en possède une (pour Chrome, elle se trouve dans Outils, Outils de développement, onglet Console). On peut y voir ceci : Creating Application Cache with manifest http://localhost/le-chemin-vers-votre-manifest Application Cache Checking event Application Cache Downloading event Application Cache Progress event (0 of 3) ... (1 of 3) ... (2 of 3) ... (3 of 3) Application Cache Cached event On y voit en effet tous les événements qui ont lieu lorsque votre navigateur met à jour son AppCache. Les plus coriaces d’entre vous souhaiterons pouvoir intercepter ces événements pour pouvoir effectuer des traitements au moment du déclenchement de ces événements. Ces événements seront détaillés dans la partie “aller plus loin” de ce tutoriel.
  • 143. App. offline Mise à jour du manifest : Attention soyez bien attentif à présent ! La phrase suivante a de quoi perturber : une fois votre application dans l’AppCache grâce au fichier manifest, c’est cette version offline qui a la priorité sur la version en ligne ! Pourquoi ? Tout simplement parce que vous lui avez justement dit de le stocker dans le cache ! C’est exactement comme lorsque votre navigateur garde en mémoire une image ou un CSS sur un site, afin de ne pas avoir à le télécharger à nouveau. Seulement, c’est un peu plus perturbant lorsqu’il est question d’un fichier HTML, je le reconnais… Et donc, comment fait-on pour mettre à jour le cache avec la version en ligne ? L’Application Cache sera mis à jour si : ● L’utilisateur vide son cache manuellement. ● Le fichier manifest change. ● Le cache est mis à jour avec du code Javascript. Voilà pourquoi il était important d’insérer un numéro de version dans un commentaire ! Il suffit de changer ce numéro de version pour obliger l’AppCache du client à se mettre à jour. Si vous effectuez peu de mises à jour (dans le cas d’un site vitrine par exemple) c’est la meilleure solution. Par contre, si vous avez besoin que le client soit en permanence à jour, on préfèrera la version Javascript. Et encore une fois, c’est dans la section “Aller plus loin” que ça se passe !
  • 144. App. offline Aller plus loin avec le manifest : La solution peut être de créer un service générant le manifest en changeant, d’une part, de version à chaque nouvel article publié et, d’autre part, en listant les URLs des derniers articles dans le cache explicite. Le chargement prendra plus de temps mais le lecteur pourra consulter l’article hors-ligne sans plus d’effort. Attention, les pages implicites qui déclarent le manifest sans être listées dans ce dernier y sont ajoutées et seront téléchargées elles aussi lors de la mise à jour du cache. Soyez prudent quand vous activez le manifest et ne multipliez pas les pages. Dans le cas du blog par exemple les pages affichant les articles ne doivent pas utiliser le manifest. Le lecteur ne souhaite certainement pas télécharger l’ensemble des articles qu’il a déjà lu à chaque nouvel article. Cette solution minimaliste peut convenir à certains, mais elle n’est pas applicable pour un site dont le contenu change beaucoup ou pour un site à fort trafic tant l’utilisation du cache est mauvaise. Pour optimiser l’utilisation du cache, il faut le considérer comme la vue statique de l’application qui évoluera au gré des changements d’interface et non au gré du contenu. Le contenu dynamique devra être servi par des requêtes asynchrones. Pour la mise en cache et le fonctionnement il faudra utiliser les nouvelles API JavaSript : LocalStorage et document.onLine. De cette manière, le manifest redeviendra un fichier statique évoluant au gré des versions de l’application. Pour garantir l’indexation du contenu par les moteurs de recherche et assurer la compatibilité avec d’anciens navigateurs, prévoyez toujours un mode dégradé sans manifest ni contenu asynchrone.
  • 145. App. offline Notes de sécurité : Notez que le cache est maintenu par nom de domaine. Il n’existe qu’une seule instance du même manifest pour un serveur. Pour les serveurs hébergeant plusieurs applications, l’utilisation d’hôte virtuel est plus que conseillée. Le cache ne doit jamais contenir de données confidentielles. Les pages de login et tous services de sécurité doivent être exclus du cache. Ne les listez jamais dans le manifest sauf pour les exclure et surtout n’intégrez pas le manifest dans ces pages. Informez l’utilisateur sur les dangers de ce service et surtout laissez le choisir d’activer ou non le fonctionnement hors ligne. En effet si le navigateur lui-même n’est pas protégé, toute personne y ayant accès pourra consulter le cache. Pour limiter le problème vous pouvez activer le service en stockant un cookie sur le navigateur si l’utilisateur active le mode hors ligne. Ainsi le lecteur devra répéter l’opération pour tous les navigateurs sur lesquels il souhaite consulter le site. En dehors de ces règles de sécurité basiques, toutes les règles de sécurité inhérentes aux sites web s’appliquent.
  • 146. App. offline L’API Javascript HTML5 possède un objet window.applicationCache. Cet objet permet de : ● connaître les états du cache ● attacher des traitements aux événements ● faire une mise à jour du cache ● changer le cache actuel Voici la classe ApplicationCache telle qu’elle est donnée par le WHATWG : interface ApplicationCache { // update status const unsigned short UNCACHED = 0; const unsigned short IDLE = 1; const unsigned short CHECKING = 2; const unsigned short DOWNLOADING = 3; const unsigned short UPDATEREADY = 4; const unsigned short OBSOLETE = 5; readonly attribute unsigned short status; // updates void update(); void swapCache(); // events attribute Function onchecking; attribute Function onerror; attribute Function onnoupdate; attribute Function ondownloading; attribute Function onprogress; attribute Function onupdateready; attribute Function oncached; attribute Function onobsolete; }; ApplicationCache implements EventTarget;
  • 147. App. offline Ainsi on peut tester le statut actuel : if (webappCache.status == window.applicationCache.UPDATEREADY) Ou avec un switch : switch (appCache.status) { case appCache.UNCACHED: // UNCACHED == 0 return 'UNCACHED'; break; case appCache.IDLE: // IDLE == 1 return 'IDLE'; break; … Mais il est préférable de passer par la gestion d’événements pour détecter lorsque l’Application Cache change de statut : var webappCache = window.applicationCache; webappCache.addEventListener("updateready", updateCache, false); webappCache.update(); function updateCache() { webappCache.swapCache(); alert("Une nouvelle version est disponible.nVeuillez rafraîchir la page pour mettre à jour."); }
  • 148. App. offline ● La méthode update() force le lancement du processus de mise à jour du cache. ● addEventListener(“updateready”, updateCache, false) lancera la fonction updateCache dès que le statut de l’AppCache passera en “updateready”. ● swapCache() permet d’échanger l’ancien cache avec le nouveau cache, ce qui finalise l’opération. Si vous souhaitez trouver de plus amples informations sur le sujet, je vous invite à vous rendre sur la page Application Cache du WHATWG, où sont listés tous les status que peut prendre applicationcache.status, et tous les événements associés. Dernière petite remarque, il est possible de tester si l’utilisateur est connecté à internet ou non avec la propriété : navigator.onLine Et voilà ! Vous avez tous les outils en main pour réaliser de superbes applications web ! Il y a fort à parier que ces applications deviendront le standard sur les smartphones d’ici quelques années, puisqu’elles fonctionnent aussi bien sur iPhone qu’Android. Couplé avec une balise canvas, on pourra par exemple jouer à des jeux vidéos en 3D dans le navigateur, qui seront compatibles avec tous les mobiles ! Pas besoin de s’embêter à développer plusieurs versions pour chaque OS mobile, du HTML/CSS et Javascript suffisent !
  • 149. App. offline Voici le code source de la page en question : <!DOCTYPE html> <html manifest="site.manifest"> <head> <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum- scale=1.0"/> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" /> <link rel="apple-touch-icon" href="earth-folder.png"> <link rel="apple-touch-icon-precomposed" href="earth-folder.png"> <link rel="apple-touch-startup-image" href="earth-folder.png" /> <style type="text/css"> #main{ width:900px; margin:auto; } </style> </head> <body> <div id="main"> <h1>Cette page est accessible hors ligne</h1> <p>Elle possède une icone d'application pour les smartphones.</p> <img src="earth-folder.png" /> </div> </body> </html>
  • 150. App. offline Le fichier site.manifest : CACHE MANIFEST # Version 0.4 exemple-application-cache-manifest-html5.html earth-folder.png Le .htaccess : AddType text/cache-manifest manifest
  • 151. App. offline ● Liens : – http://blog.xebia.fr/2010/12/02/application-hors-ligne-avec-html5- – http://diveintohtml5.info/offline.html – http://html5demo.braincracking.org/demo/onLine.php
  • 153. Framework JS Une famille nombreuse : JS client : ● http://prototypejs.org/ ● http://script.aculo.us/ ● http://mootools.net/ ● http://www.sencha.com/products/touch ● http://www.sencha.com/products/extjs ● http://www.sencha.com/products/gxt ● http://yuilibrary.com/ ● http://dojotoolkit.org/ ● http://www.angularjs.org/ ● http://meteor.com/ ● http://jquery.com/ ● http://jquerytools.org/ ● http://jqueryui.com/ ● http://jquerymobile.com/ ● http://jqtjs.com/ ● http://www.jqmobi.com/ ● http://www.bbc.co.uk/glow/ ● http://www.midorijs.com/ ● https://developers.google.com/web-toolkit/?hl=fr JS server : ● http://nodejs.org/ Comparatifs : ● http://en.wikipedia.org/wiki/Comparison_of_JavaScript_frameworks ● http://en.wikipedia.org/wiki/List_of_JavaScript_libraries
  • 155. jQuery ● La naissance de JavaScript : ● 1995 : Brendan Eich développe pour Netscape Communications Corporation, un langage de script, appelé Mocha, puis LiveScript et finalement JavaScript ● Javascript est intégré dans le navigateur Netscape 2. Succès immédiat. ● Javascript n'est pas java !! D'un point de vue des propriétés, Javascript est plus proche du langage python que du java. ● La guerre des navigateurs : ● Netscape et Microsoft (avec JScript dans Internet Explorer) ont développé leur propre variante de JavaScript avec des fonctionnalités supplémentaires et incompatibles, notamment dans la manipulation du DOM (modèle objet du navigateur WEB) ● 1997 : Adoption du standard ECMAScript. Les spécifications sont rédigées dans le document Standard ECMA-262.
  • 156. jQuery Définition de jQuery : ● Une bibliothèque javascript open-source et cross-browser ● Elle permet de traverser et manipuler très facilement l'arbre DOM des pages web à l'aide d'une syntaxe fortement similaire à celle d'XPath. ● JQuery permet par exemple de changer/ajouter une classe CSS, créer des animations, modifier des attributs, etc. ● Gérer les événements javascript ● Faire des requêtes AJAX simplement
  • 157. jQuery Ce que jQuery n’est pas : ● Un substitut pour apprendre JavaScript ● jQuery est très puissant et très pratique, mais vous devez néanmoins connaitre les bases de Javascript, notamment la partie “objet” du langage. ● Voir des livres comme : “Object Oriented Javascript de Stoyan Stefanov” ou “jQuery, novice to ninja” (google est votre ami) ● Une réponse à tout ● Utilisez jQuery uniquement lorsque c’est nécessaire. On commence toujours par HTML+CSS avant de chercher des plugins jQuery magiques. ● De nombreuses UI sont pures html+CSS
  • 158. jQuery Une simple bibliothèque à importer : Disponible sur le site de Jquery : http://jquery.com/ <script type="text/javascript" src="jquery.js"></script> Ou directement sur Google code : <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min .js"> </script>
  • 159. jQuery La fonction jQuery() : ● jQuery repose sur une seule fonction : jQuery() ou $() ● C’est une fonction JavaScript ● Elle accepte des paramètres ● Elle retourne un objet ● $ : Syntaxe issue de « Prototype »