diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/fr/web/guide | |
parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip |
initial commit
Diffstat (limited to 'files/fr/web/guide')
53 files changed, 14695 insertions, 0 deletions
diff --git a/files/fr/web/guide/ajax/communauté/index.html b/files/fr/web/guide/ajax/communauté/index.html new file mode 100644 index 0000000000..64b1ea683b --- /dev/null +++ b/files/fr/web/guide/ajax/communauté/index.html @@ -0,0 +1,14 @@ +--- +title: Communauté +slug: Web/Guide/AJAX/Communauté +tags: + - AJAX +translation_of: Web/Guide/AJAX/Community +--- +<p> +</p><p>Si vous connaissez d'autres listes de diffusion, newsgroups, forums ou d'autres communautés ayant trait à AJAX, n'hésitez pas à ajouter un lien ci-dessous. +</p><p><a href="http://www.ajaxlines.com" class=" external" rel="freelink">http://www.ajaxlines.com</a> (anglais) - Très grosse collection de ressources AJAX, de tutoriels, d'outils et de sites web sur le sujet. +</p><p><a href="http://www.ajaxmatters.com" class=" external" rel="freelink">http://www.ajaxmatters.com</a> - Portail d'informations sur AJAX et les technologies Web associées (anglais). +</p><p><br> +<span class="comment">Liens Interwikis</span> +</p>{{ languages( { "en": "en/AJAX/Community", "ja": "ja/AJAX/Community" } ) }} diff --git a/files/fr/web/guide/ajax/index.html b/files/fr/web/guide/ajax/index.html new file mode 100644 index 0000000000..18d91fe18a --- /dev/null +++ b/files/fr/web/guide/ajax/index.html @@ -0,0 +1,112 @@ +--- +title: AJAX +slug: Web/Guide/AJAX +translation_of: Web/Guide/AJAX +--- +<div class="callout-box"><strong><a href="/fr/AJAX/Premiers_pas" title="fr/AJAX/Premiers_pas">Premiers pas</a></strong><br> +Une introduction à AJAX</div> + +<div> +<p><strong>AJAX (Asynchronous JavaScript + XML)</strong> n'est pas une technologie en soi, mais un terme désignant une « nouvelle » approche utilisant un ensemble de technologies existantes, dont : <a href="/fr/HTML" title="fr/HTML">HTML</a> ou <a href="/fr/XHTML" title="fr/XHTML">XHTML</a>, <a href="/fr/CSS" title="fr/CSS">les feuilles de styles CSS</a>, <a href="/fr/JavaScript" title="fr/JavaScript">JavaScript</a>, <a href="/fr/DOM" title="fr/DOM">le modèle objet de document</a> (DOM), <a href="/fr/XML" title="fr/XML">XML</a>, <a href="/fr/XSLT" title="fr/XSLT">XSLT</a>, et l'<a href="/fr/XMLHttpRequest" title="fr/XMLHttpRequest">objet XMLHttpRequest</a>. Lorsque ces technologies sont combinées dans le modèle AJAX, les applications Web sont capables de réaliser des mises à jour rapides et incrémentielles de l'interface utilisateur sans devoir recharger la page entière du navigateur. Les applications fonctionnent plus rapidement et sont plus réactives aux actions de l'utilisateur.</p> + +<h4 id="Quand_utiliser_ou_non_AJAX"><strong>Quand utiliser (ou non) AJAX ? </strong></h4> + +<p>S'il n'y a pas de "bonne réponse", quelques éléments généraux sont à garder à mémoire : </p> + +<ul> + <li>La méthode AJAX peut être résumée comme un <u>compromis</u> : elle évite un rechargement complet de la page mais <strong>n'autorise pas davantage</strong> que ce qu'apporte une requête HTTP GET ou POST (ou HEAD) classique. Les échanges sont plutôt lourds car, même pour peu d'éléments, le navigateur <strong>doit</strong> envoyer des entêtes et négocier la transaction. <br> + La méthode est alors intérressante pour tous les sites où le contenu est changé peu fréquemment et reste prévisible : un blog, un forum, etc. où c'est l'utilisateur qui décide de changer le contenu (<em>le serveur ne peut pas être à l'initiative, sauf à faire des requêtes régulièrement mais il serait alors préférable de passer par les <a href="https://developer.mozilla.org/fr/docs/WebSockets">WebSockets</a></em>). </li> + <li>La méthode AJAX a comme qualité de rester dans les standards HTTP, en plus d'être du côté client : c'est donc une méthode qui est <strong>totalement</strong> transparente dans les échanges standards entre un client et un serveur, donc avec tous les langages de programmes qui supportent une connexion socket classique. C'est important à garder à l'esprit dans des environnements mixtes : un serveur Apache / PHP pour la génération de pages maîtresses et un contenu déployé dans un autre langage.<br> + Ne pas confondre <em>possible</em> et <em>souhaitable</em> : AJAX <strong>peut</strong> négocier avec plusieurs domaines différents ou (des ports différents dans un même domaine). Cependant pour des <a href="https://developer.mozilla.org/fr/docs/HTTP/Access_control_CORS">raisons de sécurité</a> les possibilités sont restreintes voire impossibles. La méthode AJAX est donc dépendante de ce qu'autorise ou permet le navigateur du client. </li> + <li>La méthode AJAX est connue et reconnue, pouvant être utilisées à large échelle dans des bibliothèques comme <a href="https://fr.wikipedia.org/wiki/JQuery">JQuery</a>, dont l'intérêt de ces bibliothéques est d'accélérer la vitesse de développement. De plus l'utilisation de Javascript permet d'accéder aux ressources du DOM de la page et des données reçues si elles sont au format XML, permettant la sérialisation dans la plupart des situations. <br> + Cependant AJAX rencontre aussi les difficultés liées à la grande hétérogénité des navigateurs (implantation différente de JS, donc<em> in fine</em> des possibilités AJAX), des règles de sécurité, etc. Comme pour CSS, AJAX peut être vu comme un "plus" dans la navigation (<em>voir le principe de <a href="https://fr.wikipedia.org/wiki/Am%C3%A9lioration_progressive">dégradation élégante</a></em>) mais ne doit pas être vu comme une finalité au risque, sinon, de se couper d'une partie des utilisateurs. </li> +</ul> +</div> + +<table class="topicpage-table"> + <tbody> + <tr> + <td> + <h2 class="Documentation" id="Documentation">Documentation</h2> + + <dl> + <dt><a href="/fr/AJAX/Premiers_pas" title="fr/AJAX/Premiers_pas">AJAX:Premiers pas</a></dt> + <dd><small>Cet article vous guide à travers les bases d'AJAX et vous donne deux exemples simples pour commencer.</small></dd> + </dl> + + <dl> + <dt><a class="external" href="http://www.webreference.com/programming/ajax_tech/">Techniques AJAX alternatives</a></dt> + <dd><small>La plupart des articles sur AJAX se concentrent sur l'utilisation de XMLHttp comme moyen de communication, mais les techniques AJAX ne s'arrêtent pas à XMLHttp. Il y en a bien d'autres.</small></dd> + </dl> + + <dl> + <dt><a class="external" href="http://www.adaptivepath.com/publications/essays/archives/000385.php">Ajax: A New Approach to Web Applications (en)</a></dt> + <dd><small>Jesse James Garrett, du site <a class="external" href="http://www.adaptivepath.com">adaptive path</a>, a écrit cet article en février 2005, introduisant le terme AJAX et les concepts liés.</small></dd> + </dl> + + <dl> + <dt><a class="external" href="http://www.onlamp.com/pub/a/onlamp/2005/05/19/xmlhttprequest.html">A Simpler Ajax Path</a></dt> + <dd><small>« Comme on le remarquera, il est assez facile de tirer parti de l'objet XMLHttpRequest pour faire se comporter une application Web un peu plus comme une application traditionnelle, tout en continuant à utiliser des outils comme des formulaires Web pour collecter les entrées de l'utilisateur. »</small></dd> + </dl> + + <dl> + <dt><a class="external" href="http://www.contentwithstyle.co.uk/Articles/38/fixing-the-back-button-and-enabling-bookmarking-for-ajax-apps">Fixing the Back Button and Enabling Bookmarking for AJAX Apps</a></dt> + <dd><small>Cet article rédigé par Mike Stenhouse détaille certaines méthodes utilisables pour rendre fonctionnel le bouton Précédent et réparer les problèmes causés au marquage des pages lorsque des applications sont développées avec les outils AJAX.</small></dd> + </dl> + + <dl> + <dt><a class="external" href="http://alexbosworth.backpackit.com/pub/67688">Ajax Mistakes</a></dt> + <dd><small>Cet article d'Alex Bosworth attire l'attention sur certaines erreurs que les développeurs d'applications AJAX peuvent faire.</small></dd> + </dl> + + <dl> + <dt><a class="external" href="http://www.xul.fr/xml-ajax.html" title="http://www.xul.fr/xml-ajax.html">Tutoriel</a> avec des exemples.</dt> + </dl> + + <dl> + <dt><a class="external" href="http://www.w3.org/TR/XMLHttpRequest/">La spécification XMLHttpRequest</a>- <a class="external" href="http://www.xul.fr/XMLHttpRequest.html" title="http://www.xul.fr/XMLHttpRequest.html">(Traduction française)</a></dt> + <dd><small>Brouillon de travail du W3C</small></dd> + </dl> + + <p><span class="alllinks"><a href="/Special:Tags?tag=AJAX&language=fr" title="Special:Tags?tag=AJAX&language=fr">Tous les articles…</a></span></p> + </td> + <td> + <h2 class="Community" id="Communauté">Communauté</h2> + + <ul> + <li>Voir les forums de Mozilla… {{ DiscussionList("dev-ajax", "mozilla.dev.ajax") }}</li> + </ul> + + <h2 class="Tools" id="Outils">Outils</h2> + + <ul> + <li><a class="external" href="http://www.ajaxprojects.com">Toolkits et frameworks</a></li> + <li><a class="external" href="http://www.getfirebug.com/">Firebug — Outil de développement AJAX/Web</a></li> + <li><a class="external" href="http://blog.monstuff.com/archives/000252.html">Outils de débogage AJAX</a></li> + <li><a class="external" href="http://www.osflash.org/doku.php?id=flashjs">Kit d'intégration Flash/AJAX</a></li> + <li><a class="external" href="http://xkr.us/code/javascript/XHConn/">Une bibliothèque d'interface XMLHTTP simple</a></li> + <li><a class="external" href="http://chandlerproject.org/Projects/AjaxLibraries">Bibliothèques AJAX</a> <span class="alllinks"><a href="/Special:Tags?tag=AJAX:Outils&language=fr" title="Special:Tags?tag=AJAX:Outils&language=fr">Tous les outils…</a></span></li> + </ul> + + <h2 id="Exemples">Exemples</h2> + + <ul> + <li><a class="external" href="http://www.dhtmlgoodies.com/index.html?whichScript=ajax-poller">AJAX poller script</a></li> + <li><a class="external" href="http://www.ajaxprojects.com/ajax/tutorialdetails.php?itemid=9">Ajax Chat Tutorial</a></li> + <li><a class="external" href="http://www.funwithjustin.com/ajax-toybox/">Ajax Toybox</a></li> + <li><a class="external" href="http://www.ajaxprojects.com/ajax/tutorialdetails.php?itemid=13">RSS Ticker with AJAX</a></li> + <li><a class="external" href="http://www.jamesdam.com/ajax_login/login.html#login">AJAX Login System using XMLHttpRequest</a></li> + <li><a class="external" href="http://www.thinkvitamin.com/features/ajax/create-your-own-ajax-effects">Create your own Ajax effects</a></li> + <li><a class="external" href="http://codinginparadise.org/weblog/2005/08/ajax-creating-huge-bookmarklets.html">AJAX: Creating Huge Bookmarklets</a></li> + <li><a class="external" href="http://www.hotajax.org">Hot!Ajax: many cool examples</a></li> + </ul> + + <h2 class="Related_Topics" id="Sujets_liés">Sujets liés</h2> + + <dl> + <dd><a href="/fr/HTML" title="fr/HTML">HTML</a>, <a href="/fr/XHTML" title="fr/XHTML">XHTML</a>, <a href="/fr/CSS" title="fr/CSS">Feuilles de style (CSS)</a>, <a href="/fr/DOM" title="fr/DOM">Modèle objet de document (DOM)</a>, <a href="/fr/JavaScript" title="fr/JavaScript">JavaScript</a>, <a href="/fr/XML" title="fr/XML">XML</a>, <a href="/fr/XSLT" title="fr/XSLT">XSLT</a> , <a href="/fr/DHTML" title="fr/DHTML">DHTML</a>, <a href="/fr/HTML/Canvas" title="fr/HTML/Canvas">Canvas</a></dd> + </dl> + </td> + </tr> + </tbody> +</table> diff --git a/files/fr/web/guide/ajax/premiers_pas/index.html b/files/fr/web/guide/ajax/premiers_pas/index.html new file mode 100644 index 0000000000..bce7938f0f --- /dev/null +++ b/files/fr/web/guide/ajax/premiers_pas/index.html @@ -0,0 +1,275 @@ +--- +title: Premiers pas +slug: Web/Guide/AJAX/Premiers_pas +tags: + - AJAX +translation_of: Web/Guide/AJAX/Getting_Started +--- +<p>Cet article vous guide à travers les bases d’AJAX et vous donne deux exemples clefs-en-main pour débuter.</p> + +<h3 id="Pr.C3.A9sentation_d.27AJAX" name="Pr.C3.A9sentation_d.27AJAX">Présentation d’AJAX</h3> + +<p>AJAX est un raccourci pour <em><strong>A</strong>synchronous <strong>J</strong>avaScript <strong>A</strong>nd <strong>X</strong>ML</em> (JavaScript asynchrone et XML) inventé par Jesse James Garrett. Pour simplifier, il s’agit d’employer l’objet <code><a href="/fr/XMLHttpRequest" title="fr/XMLHttpRequest">XMLHttpRequest</a></code> pour communiquer avec des serveurs. Il peut envoyer et recevoir des informations sous différents formats, dont JSON, XML, HTML ou texte. Son principal attrait est sa nature « asynchrone » ce qui signifie qu’il peut communiquer avec le serveur, échanger des données et mettre à jour la page sans avoir à la recharger.</p> + +<p>Les deux principales fonctionnalités d’AJAX permettent de :</p> + +<ul> + <li>faire des requêtes vers le serveur sans recharger la page ;</li> + <li>recevoir et travailler avec des données provenant du serveur.</li> +</ul> + +<h3 id=".C3.89tape_1_.E2.80.94_Lancement_d.27une_requ.C3.AAte_HTTP" name=".C3.89tape_1_.E2.80.94_Lancement_d.27une_requ.C3.AAte_HTTP">Étape 1 — Lancement d’une requête HTTP</h3> + +<p>Pour faire une requête <a href="/HTTP">HTTP</a> vers le serveur à l’aide de JavaScript, il faut disposer d’une instance d’objet fournissant cette fonctionnalité. C’est ici que <code>XMLHttpRequest</code> intervient. Son prédécesseur est originaire de Internet Explorer sous la forme d’un objet ActiveX appelé <code>XMLHTTP</code>. Par la suite, Mozilla, Safari et d’autres navigateurs ont suivi en implémentant un objet <code>XMLHttpRequest</code> qui fournit les mêmes méthodes et propriétés que l’objet ActiveX original de Microsoft. Entre temps, Microsoft a également implémenté XMLHttpRequest.</p> + +<pre class="brush: js">// ancien code de compatibilité, aujourd’hui inutile +if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+... + httpRequest = new XMLHttpRequest(); +} +else if (window.ActiveXObject) { // IE 6 et antérieurs + httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); +}</pre> + +<div class="blockIndicator note"> +<p><strong>Note :</strong> Pour illustrer le principe, le code ci-dessus est une version un peu simplifiée de celui qui est utilisé pour créer une instance XMLHTTP. Pour un exemple plus réaliste, voir l’étape 3 de cet article.</p> +</div> + +<p>Après avoir fait une requête, vous recevrez une réponse du serveur. À ce stade, vous devez indiquer à l’objet <code>httpRequest</code> le nom de la fonction JavaScript qui traitera la réponse. Pour cela, assignez à la propriété <code>onreadystatechange</code> de l’objet le nom de la fonction JavaScript que vous envisagez d’utiliser, comme ceci :</p> + +<pre class="brush: js">httpRequest.onreadystatechange = nomDeLaFonction;</pre> + +<p>Notez qu’il n’y a ni parenthèses ni paramètres après le nom de la fonction, car vous ne faites qu’assigner une référence à la fonction sans l’appeler réellement. Alternativement, au lieu de donner un nom de fonction, vous pouvez utiliser la technique JavaScript de définition de fonctions à la volée (ce qu’on appelle une fonction anonyme), et définir à cet endroit les actions à effectuer sur la réponse, comme ceci :</p> + +<pre class="brush: js">httpRequest.onreadystatechange = function() { + // instructions de traitement de la réponse +}; +</pre> + +<p>Ensuite, après avoir déclaré ce qui se produit lorsque la réponse est reçue, il s’agit de lancer effectivement la requête. Il faut pour cela appeler les méthodes <code>open()</code> et <code>send()</code> de l’objet <code>httpRequest</code>, comme ceci :</p> + +<pre class="brush: js">httpRequest.open('GET', 'http://www.example.org/some.file', true); +httpRequest.send();</pre> + +<ul> + <li>Le premier paramètre de l’appel à <code>open()</code> est la méthode de requête HTTP — GET, POST, HEAD ou toute autre méthode gérée par votre serveur. Laissez le nom de la méthode en majuscules comme spécifié par la norme HTTP ; autrement certains navigateurs (comme Firefox) peuvent ne pas traiter la requête. Pour plus d’informations sur les méthodes de requêtes HTTP possibles, vous pouvez consulter les <a class="external" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html">spécifications du W3C</a>.</li> + <li>Le second paramètre est l’URL à laquelle vous envoyez la requête. Pour des raisons de sécurité, il est par défaut impossible d’appeler des URL se situant sur un domaine de tierce-partie. Veillez à utiliser le nom de domaine exact sur toutes vos pages ou vous obtiendrez une erreur « permission refusée » lors de l’appel à <code>open()</code>. Une erreur courante est de charger le site via <code>domaine.tld</code>, mais d’essayer d’appeler des pages avec <code>www.domain.tld</code>. Si vous avez réellement besoin d’envoyer une requête vers un autre domaine, veuillez consulter <a href="/fr/docs/Web/HTTP/CORS">Cross-Origin Resource Sharing (CORS)</a>.</li> + <li>Le troisième paramètre, optionnel, précise si la requête est asynchrone. Si mis à <code>true</code> (sa valeur par défaut), l’exécution de JavaScript se poursuivra, et l’utilisateur ou l’utilisatrice pourra interagir avec la page, en attendant l’arrivée de la réponse du serveur. C’est le premier « A » de « AJAX ».</li> +</ul> + +<p>Le paramètre de la méthode <code>send()</code> peut être n’importe quelle donnée que vous voulez envoyer au serveur en cas d’utilisation de la méthode POST. Les données doivent être sous la forme d’une chaîne de requête, comme :</p> + +<pre class="brush: js">"nom=valeur&autrenom="+encodeURIComponent(autrevaleur)+"&ainsi=desuite"</pre> + +<p>Ou d’autres formats tels que <code>multipart/form-data</code>, JSON, XML, etc.</p> + +<p>Notez que si vous voulez envoyer des données avec la méthode POST, vous aurez peut-être à changer le type MIME de la requête. Par exemple, utilisez ce qui suit avant d’appeler <code>send()</code> pour envoyer des données de formulaire en tant que chaîne de requête :</p> + +<pre class="brush: js">httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); +</pre> + +<h3 id=".C3.89tape_2_.E2.80.94_Gestion_de_la_r.C3.A9ponse_du_serveur" name=".C3.89tape_2_.E2.80.94_Gestion_de_la_r.C3.A9ponse_du_serveur">Étape 2 — Gestion de la réponse du serveur</h3> + +<p>Lors de l’envoi de la requête, vous avez désigné une fonction JavaScript pour traiter la réponse.</p> + +<pre class="brush: js"><code>httpRequest.onreadystatechange = nomDeLaFonction;</code></pre> + +<p>Voyons maintenant ce que cette fonction doit faire. Tout d’abord, elle doit vérifier l’état de la requête. Si cet état a la valeur de <code>XMLHttpRequest.DONE</code> (ce qui correspond à 4), cela signifie que la réponse du serveur a été reçue dans son intégralité et qu’elle peut maintenant être traitée.</p> + +<pre class="brush: js">if (httpRequest.readyState === XMLHttpRequest.DONE) { + // tout va bien, la réponse a été reçue +} else { + // pas encore prête +}</pre> + +<p>La liste complète des valeurs de <code>readyState</code> est documentée sur <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#Properties">XMLHttpRequest.readyState</a> et se résume de cette façon :</p> + +<ul> + <li>0 (non initialisée) ou (requête non initialisée)</li> + <li>1 (en cours de chargement) ou (connexion établie avec le serveur)</li> + <li>2 (chargée) ou (requête reçue)</li> + <li>3 (en cours d’interaction) ou (requête en cours de traitement)</li> + <li>4 (terminée) ou (requête terminée et réponse prête)</li> +</ul> + +<p>Ensuite, vérifiez le <a href="/fr/docs/Web/HTTP/Status">code de statut HTTP</a> de la réponse du serveur. Tous les codes possibles sont listés sur le <a class="external" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">site du W3C</a>. Dans l’exemple qui suit, nous différencions un appel réussi ou échoué en vérifiant la réception d’un code <code><a href="/fr/docs/Web/HTTP/Status#R%C3%A9ponses_de_succ%C3%A8s">200 OK</a></code>.</p> + +<pre class="brush: js">if (httpRequest.status === 200) { + // parfait ! +} else { + // il y a eu un problème avec la requête, + // par exemple la réponse peut être un code 404 (Non trouvée) + // ou 500 (Erreur interne au serveur) +} +</pre> + +<p>Après avoir vérifié l’état de la requête et le code de statut HTTP de la réponse, vous pouvez traiter à votre guise les données envoyées par le serveur. Il existe deux manières d’accéder à ces données :</p> + +<ul> + <li><code>httpRequest.responseText</code> — renvoie la réponse du serveur sous la forme d’une chaîne de texte ;</li> + <li><code>httpRequest.responseXML</code> — renvoie la réponse sous la forme d’un objet <code>XMLDocument</code> que vous pouvez parcourir à l’aide des fonctions DOM de JavaScript.</li> +</ul> + +<p>Notez que les étapes ci-dessus sont valides uniquement si vous utilisez une requête asynchrone (Le 3e paramètre d’<code>open()</code> n’a pas été spécifié, ou a été défini à <code>true</code>). Si vous utilisez une requête <strong>synchrone,</strong> vous n’avez pas besoin de spécifier une fonction, mais c’est fortement découragé car cela entraîne une mauvaise expérience utilisateur.</p> + +<h3 id=".C3.89tape_3_.E2.80.94_Un_exemple_simple" name=".C3.89tape_3_.E2.80.94_Un_exemple_simple">Étape 3 — Un exemple simple</h3> + +<p>Rassemblons tous ces éléments dans un exemple : une requête HTTP simple. Notre JavaScript demande un document HTML, <code>test.html</code>, qui contient le texte « Je suis un test. », puis nous affichons le contenu de la réponse dans un message <code>alert()</code>. Remarquez que cet exemple n’utilise que du pur JavaScript vanilla (pas de jQuery). D’autre part, les fichiers HTML, XML et PHP doivent être placés dans le même dossier.</p> + +<pre class="brush: html"><button id="ajaxButton" type="button">Faire une requête</button> + +<script> +(function() { + var httpRequest; + document.getElementById("ajaxButton").addEventListener('click', makeRequest); + + function makeRequest() { + httpRequest = new XMLHttpRequest(); + + if (!httpRequest) { + alert('Abandon :( Impossible de créer une instance de XMLHTTP'); + return false; + } + httpRequest.onreadystatechange = alertContents; + httpRequest.open('GET', 'test.html'); + httpRequest.send(); + } + + function alertContents() { + if (httpRequest.readyState === XMLHttpRequest.DONE) { + if (httpRequest.status === 200) { + alert(httpRequest.responseText); + } else { + alert('Il y a eu un problème avec la requête.'); + } + } + } +})(); +</script></pre> + +<p>Dans cet exemple :</p> + +<ul> + <li>L’utilisateur ou l’utilisatrice clique sur le bouton « Faire une requête » ;</li> + <li>Le gestionnaire d’évènement appelle la fonction <code>makeRequest()</code> ;</li> + <li>la requête est faite, puis l’exécution est passée à <code>alertContents()</code> (via <code>onreadystatechange</code>);</li> + <li><code>alertContents()</code> vérifie si la réponse reçue est correcte, et affiche ensuite le contenu du fichier <code>test.html</code> dans un message <code>alert()</code>.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Note :</strong> Si vous envoyez une requête à du code qui renvoie du XML plutôt qu’un fichier HTML statique, vous devez spécifier des en-têtes de réponse pour que cela fonctionne avec Internet Explorer. Si vous ne spécifiez pas l’en-tête <code>Content-Type: application/xml</code>, IE émettra une erreur JavaScript « Objet attendu » après la ligne à laquelle vous avez tenté d’accéder à l’élément XML.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Note 2 :</strong> Si vous ne spécifiez pas l’en-tête <code>Cache-Control: no-cache</code>, le navigateur mettra la réponse en cache et n’effectuera plus jamais la requête ultérieurement, ce qui peut rendre le débogage difficile. Vous pouvez également ajouter un paramètre GET toujours différent, comme un timestamp ou un nombre aléatoire (voir <a href="https://developer.mozilla.org/fr/docs/Web/API/XMLHttpRequest/Utiliser_XMLHttpRequest#Contourner_le_cache">contourner le cache</a>).</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Note 3 :</strong> Si la variable <code>httpRequest</code> est utilisée globalement, des appels concurrents à <code>makeRequest()</code> peuvent s’écraser l’un l’autre, provoquant une situation de compétition <em>(race condition</em>). On peut s’en prémunir en déclarant la variable <code>httpRequest</code> locale à une <a href="/fr/docs/Web/JavaScript/Closures">closure</a> contenant les fonctions AJAX.</p> +</div> + +<p>Si une erreur de communication se produit (par exemple le serveur qui cesse de répondre), une exception sera levée dans la méthode <code>onreadystatechange</code> lors de l’accès à la propriété <code>status</code>. Pour atténuer ce problème, vous pouvez entourer votre bloc <code>if...then</code> dans un <code>try...catch</code> :</p> + +<pre class="brush: js">function alertContents(httpRequest) { + try { + if (httpRequest.readyState === XMLHttpRequest.DONE) { + if (httpRequest.status === 200) { + alert(httpRequest.responseText); + } else { + alert("Un problème est survenu au cours de la requête."); + } + } + } + catch( e ) { + alert("Une exception s’est produite : " + e.description); + } +}</pre> + +<h3 id=".C3.89tape_4_.E2.80.94_Travailler_avec_des_r.C3.A9ponses_XML" name=".C3.89tape_4_.E2.80.94_Travailler_avec_des_r.C3.A9ponses_XML">Étape 4 — Travailler avec des réponses XML</h3> + +<p class="brush: xml">Dans l’exemple précédent, après avoir reçu la réponse à la requête HTTP, nous avons utilisé la propriété <code>responseText</code> de l’objet, qui contenait le contenu du fichier <code>test.html</code>. Essayons maintenant la propriété <code>responseXML</code>.</p> + +<p>Tout d’abord, créons un document XML valide qui sera l’objet de la requête. Le document (<code>test.xml</code>) contient ce qui suit :</p> + +<pre class="brush: xml"><?xml version="1.0" ?> +<root> + Je suis un test. +</root> +</pre> + +<p>Dans le script, il est seulement nécessaire de remplacer la ligne de requête par :</p> + +<pre class="brush: html">... +onclick="makeRequest('test.xml')"> +... +</pre> + +<p>Ensuite, dans <code>alertContents()</code>, il faut remplacer la ligne <code>alert(httpRequest.responseText);</code> par :</p> + +<pre class="brush: js">var xmldoc = httpRequest.responseXML; +var root_node = xmldoc.getElementsByTagName('root').item(0); +alert(root_node.firstChild.data); +</pre> + +<p>Ce code prend l’objet <code>XMLDocument</code> donné par <code>responseXML</code> et utilise les méthodes du DOM pour accéder à des données contenues dans le document XML.</p> + +<p><span class="comment">Catégories</span></p> + +<p><span class="comment">Interwiki</span></p> + +<h3 id="Étape_5_–_Manipuler_les_données">Étape 5 – Manipuler les données</h3> + +<p>Pour finir, envoyons quelques données au serveur et réceptionnons la réponse. Notre JavaScript demandera cette fois-ci une page dynamique, <code>test.php</code>, qui prendra notre contenu envoyé et revera une chaîne « calculée » – "Bonjour, [user data] !" – que nous afficherons via <code>alert()</code>.</p> + +<p>D’abord, nous allons ajouter un boîte de texte dans notre HTML afin que l’utilisateur ou l’utilisatrice puisse saisir son nom :</p> + +<pre class="brush: html"><label>Vore nom : + <input type="text" id="ajaxTextbox" /> +</label> +<span id="ajaxButton" style="cursor: pointer; text-decoration: underline"> + Lancer une requête +</span></pre> + +<p>Nous allons également ajouter une ligne à notre gestionnaire d’événement pour obtenir les données de la boite de texte et les envoyer à la fonction <code>makeRequest()</code>, ainsi que l’URL de notre script côté serveur :</p> + +<pre class="brush: js"> document.getElementById("ajaxButton").onclick = function() { + var userName = document.getElementById("ajaxTextbox").value; + makeRequest('test.php', userName); + };</pre> + +<p>Nous devons modifier <code>makeRequest()</code> afin d’accepter les données et les transmettre au serveur. Nous changerons la méthode de GET à POST et inclurons nos données en paramètres dans l’appel à <code>httpRequest.send()</code> :</p> + +<pre class="brush: js"> function makeRequest(url, userName) { + + ... + + httpRequest.onreadystatechange = alertContents; + httpRequest.open('POST', url); + httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + httpRequest.send('userName=' + encodeURIComponent(userName)); + }</pre> + +<p>La fonction <code>alertContents()</code> peut être écrite de la même manière qu’à l’étape 3 pour afficher notre chaîne calculée, si c’est tout ce que le serveur renvoie. Cependant, supposons que le serveur renvoie à la fois la phrase calculée et la donnée originale. Donc si l’utilisateur ou l’utilisatrice a saisi « Dorothée », la réponse du serveur ressemblera à :</p> + +<pre class="brush: json">{"userData":"Dorothée","computedString":"Bonjour, Dorothée !"}</pre> + +<p>Pour utiliser cette phrase dans <code>alertContents()</code>, nous ne pouvons pas simplement afficher une alerte avec le contenu de <code>responseText</code>, nous devons l’analyser et afficher <code>computedString</code>, la propriété que nous souhaitons :</p> + +<pre class="brush: js">function alertContents() { + if (httpRequest.readyState === XMLHttpRequest.DONE) { + if (httpRequest.status === 200) { + var response = JSON.parse(httpRequest.responseText); + alert(response.computedString); + } else { + alert('Un problème est survenu avec la requête.'); + } + } +}</pre> + +<p>Le fichier <code>test.php</code> devrait contenir ce qui suit :</p> + +<pre class="brush: php">$name = (isset($_POST['userName'])) ? $_POST['userName'] : 'anonyme'; +$computedString = 'Bonjour, ' . $name . ' !'; +$array = ['userName' => $name, 'computedString' => $computedString]; +echo json_encode($array);</pre> + +<p>Pour en savoir sur les méthodes DOM, pensez à lire la <a href="/fr/docs/Web/API/Document_Object_Model">Référence du DOM</a> de Mozilla.</p> diff --git a/files/fr/web/guide/api/gamepad/index.html b/files/fr/web/guide/api/gamepad/index.html new file mode 100644 index 0000000000..1cfa50fc2c --- /dev/null +++ b/files/fr/web/guide/api/gamepad/index.html @@ -0,0 +1,281 @@ +--- +title: Utiliser l'API Gamepad +slug: Web/Guide/API/Gamepad +translation_of: Web/API/Gamepad_API/Using_the_Gamepad_API +--- +<p>{{ SeeCompatTable() }}</p> +<div class="summary"> + <p><span class="seoSummary">HTML5 a introduit plusieurs des composants nécessaires pour le développement de jeux vidéos riches et interactifs. Des technologies comme <code><canvas></code>, WebGL, <code><audio></code>, et <code><video></code>, ainsi que les implémentations JavaScript, ont mûri au point de supporter plusieurs fonctions autrefois réservées aux applications natives.</span> L'API Gamepad est une manière pour les développeurs et <em><code>designers</code></em> d'accéder aux contrôleurs de jeux.</p> +</div> +<div class="note"> + <p><strong>Note</strong><strong>:</strong> Dans Firefox 29 et plus, l'API Gamepad est activée par défaut, tout comme pour les versions Nightly et Aurora. Depuis Firefox 24, l'API Gamepad était déjà disponible derrière une option dans les préférences. Il est possible de l'activer dans ces versions en ouvrant <code>about:config</code> et en activant <code>dom.gamepad.enabled</code>.</p> +</div> +<p>L'API Gamepad introduit de nouveaux évènements à l'objet {{ domxref("Window") }} pour lire l'état des contrôleurs. En plus de ces événements, l'API ajoute aussi un objet {{ domxref("Gamepad") }} que vous pouvez utiliser pour récupérer l'état d'un contrôleur connecté, et une méthode {{ domxref("navigator.getGamepads") }} que vous pouvez utiliser pour obtenir la liste des contrôleurs connus par la page.</p> +<h2 id="conntecting" name="conntecting">Connexion au contrôleur</h2> +<p>Lorsqu'un nouveau contrôleur est connecté à l'ordinateur, la page active reçoit tout d'abord un événement {{ domxref("Window.gamepadconnected") }}. Si un contrôleur est déjà connecté lorsque la page termine de charger, l'événement {{ domxref("Window.gamepadconnected") }} est envoyé à la page active lorsque l'utilisateur appuie sur un bouton ou bouge un axe.</p> +<div class="geckoVersionNote"> + <p>Dans Firefox, les contrôleurs ne sont rendus visibles à une page que lorsque l'utilisateur s'en sert alors que cette page est active. Cela permet d'éviter que les contrôleurs soient utilisés pour identifier l'utilisateur. Dès lors qu'un contrôleur a été utilisé, les autres contrôleurs connectés seront rendus visibles automatiquement.</p> +</div> +<p>Vous pouvez utiliser {{ domxref("Window.gamepadconnected") }} ainsi :</p> +<pre class="brush: js">window.addEventListener("gamepadconnected", function(e) { + console.log("Contrôleur n°%d connecté : %s. %d boutons, %d axes.", + e.gamepad.index, e.gamepad.id, + e.gamepad.buttons.length, e.gamepad.axes.length); +}); +</pre> +<p>Chaque contrôleur est associé à un identifiant unique, qui est disponible dans la propriété <code>gamepad</code> de l'événement.</p> +<div class="note"> + <p><strong>Note</strong>: À l'écriture de ces lignes, Chrome n'implémente pas les événements {{ domxref("Window.gamepadconnected") }} et {{ domxref("Window.gamepaddisconnected") }}. Vous devez utiliser {{ domxref("navigator.getGamepads") }} pour récupérer la liste des contrôleurs disponibles.</p> +</div> +<h2 id="disconnecting" name="disconnecting">Déconnexion du contrôleur</h2> +<p>Lorsqu'un contrôleur est déconnecté, et si la page avait déjà reçu des données de ce contrôleur auparavant (par exemple par l'événement {{ domxref("Window.gamepadconnected") }}), un second événement est envoyé à la fenêtre active : <span style="line-height: 1.5;"> {{ domxref("Window.gamepaddisconnected") }}.</span></p> +<pre class="brush: js">window.addEventListener("gamepaddisconnected", function(e) { + console.log("Contrôleur n°%d déconnecté : %s", + e.gamepad.index, e.gamepad.id); +});</pre> +<p>La propriété <code>index</code> sera unique à chaque périphérique connecté au système, même si plusieurs contrôleurs du même type sont utilisés. La propriété correspond également à l'indice du tableau retourné par<span style="line-height: 1.5;"> {{ domxref("navigator.getGamepads") }}.</span></p> +<pre class="brush: js">var gamepads = {}; + +function gamepadHandler(event, connecting) { + var gamepad = event.gamepad; + // Note : + // gamepad === navigator.getGamepads()[gamepad.index] + + if (connecting) { + gamepads[gamepad.index] = gamepad; + } else { + delete gamepads[gamepad.index]; + } +} + +window.addEventListener("gamepadconnected", function(e) { gamepadHandler(e, true); }, false); +window.addEventListener("gamepaddisconnected", function(e) { gamepadHandler(e, false); }, false); +</pre> +<p>Cet exemple montre également comment la propriété <code>gamepad</code> peut être conservée après que l'événement se soit terminé. Cette technique sera utilisée plus tard pour obtenir l'état du périphérique.</p> +<div> + [PAGE NON TRADUITE DEPUIS ICI...]</div> +<div> + </div> +<h2 id="querying" name="querying">Querying the Gamepad object</h2> +<p>As you can see, the <strong>gamepad</strong> events discussed above include a <code>gamepad</code> property on the event object, which returns a {{ domxref("Gamepad") }} object. We can use this in order to determine which gamepad (i.e., its ID) had caused the event, since multiple gamepads might be connected at once. We can do much more with the {{ domxref("Gamepad") }} object, including holding a reference to it and querying it to find out which buttons and axes are being pressed at any one time. Doing so is often desirable for games or other interactive web pages that need to know the state of a gamepad now vs. the next time an event fires.</p> +<p>Performing such checks tends to involve using the {{ domxref("Gamepad") }} object in conjunction with an animation loop (e.g., {{ domxref("requestAnimationFrame") }}), where developers want to make decisions for the current frame based on the state of the gamepad or gamepads.</p> +<div class="note"> + <p><strong>Note</strong>: The Gamepad API also provides a function -- {{ domxref("Navigator.getGamepads") }}-- that returns a list of all devices currently visible to the webpage, an array of {{ domxref("Gamepad") }} objects. This can then be used to get the same information. For example, the first code example above you be rewritten as shown below:</p> +</div> +<pre class="brush: js">window.addEventListener("gamepadconnected", function(e) { + var gp = navigator.getGamepads()[e.gamepad.index]; + console.log("Gamepad connected at index %d: %s. %d buttons, %d axes.", + gp.index, gp.id, + gp.buttons.length, gp.axes.length); +});</pre> +<p>The {{ domxref("Gamepad") }} object's properties are as follows:</p> +<ul> + <li><code>id</code>: A string containing some information about the controller. This is not strictly specified, but in Firefox it will contain three pieces of information separated by dashes (<code>-</code>): two 4-digit hexadecimal strings containing the USB vendor and product id of the controller, and the name of the controller as provided by the driver. This information is intended to allow you to find a mapping for the controls on the device as well as display useful feedback to the user.</li> + <li><code>index</code>: An integer that is unique for each gamepad currently connected to the system. This can be used to distinguish multiple controllers. Note that disconnecting a device and then connecting a new device may reuse the previous index.</li> + <li><code>mapping</code>: A string indicating whether the browser has remapped the controls on the device to a known layout. Currently there is only one supported known layout–the <a href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#remapping">standard gamepad</a>. If the browser is able to map controls on the device to that layout the <code>mapping</code> property will be set to the string <code>standard</code>.</li> + <li><code>connected</code>: A boolean indicating whether the gamepad is still connected to the system. If this is so the value is <code>True</code>; if not, it is <code>False</code>.</li> + <li><code>buttons</code>: An array of {{ domxref("GamepadButton") }} objects representing the buttons present on the device. Each {{ domxref("GamepadButton") }} has a <code>pressed</code> and a <code>value</code> property: + <ul> + <li>The <code>pressed</code> property is a boolean indicating whether the button is currently pressed (<code>true</code>) or unpressed (<code>false</code>).</li> + <li>The <code>value</code> property is a floating point value used to enable representing analog buttons, such as the triggers on many modern gamepads. The values are normalized to the range 0.0..1.0, with 0.0 representing a button that is not pressed, and 1.0 representing a button that is fully pressed.</li> + </ul> + </li> + <li><code>axes</code>: An array representing the controls with axes present on the device (e.g. analog thumb sticks). Each entry in the array is a floating point value in the range -1.0 - 1.0, representing the axis position from the lowest value (-1.0) to the highest value (1.0).</li> + <li><code>timestamp</code>: This returns a {{ domxref("DOMHighResTimeStamp") }} representing the last time the data for this gamepad was updated, allowing developers to determine if the <code>axes</code> and <code>button</code> data have been updated from the hardware. The value must be relative to the <code>navigationStart</code> attribute of the {{ domxref("PerformanceTiming") }} interface. Values are monotonically increasing, meaning that they can be compared to determine the ordering of updates, as newer values will always be greater than or equal to older values. Note that this property is not currently supported in Firefox.</li> +</ul> +<div class="note"> + <p><strong>Note</strong>: The Gamepad object is available on the {{ domxref("Window.gamepadconnected") }} event rather than the {{ domxref("Window") }} object itself, for security reasons. Once we have a reference to it, we can query its properties for information about the current state of the gamepad. Behind the scenes, this object will be updated every time the gamepad's state changes.</p> +</div> +<h3 id="Using_button_information">Using button information</h3> +<p>Let's look at a simple example that displays connection information for one gamepad (it ignores subsequent gamepad connections) and allows you to move a ball around the screen using the four gamepad buttons on the right hand side of the gamepad. You can <a href="http://chrisdavidmills.github.io/gamepad-buttons/">view the demo live</a>, and <a href="https://github.com/chrisdavidmills/gamepad-buttons/tree/master">find the source code</a> on Github.</p> +<p>To start with, we declare some variables: The <code>gamepadInfo</code> paragraph that the connection info is written into, the <code>ball</code> that we want to move, the <code>start</code> variable that acts as the ID for <code>requestAnimation Frame</code>, the <code>a</code> and <code>b</code> variables that act as position modifiers for moving the ball, and the shorthand variables that will be used for the {{ domxref("requestAnimationFrame") }} and {{ domxref("cancelRequestAnimationFrame") }} cross browser forks.</p> +<pre class="brush: js">var gamepadInfo = document.getElementById("gamepad-info"); +var ball = document.getElementById("ball"); +var start; +var a = 0; +var b = 0; + +var rAF = window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || + window.requestAnimationFrame; + +var rAFStop = window.mozCancelRequestAnimationFrame || + window.webkitCancelRequestAnimationFrame || + window.cancelRequestAnimationFrame;</pre> +<p>Next we use the {{ domxref("Window.gamepadconnected") }} event to check for a gamepad being connected. When one is connected, we grab the gamepad using {{ domxref("Navigator.getGamepads") }}<code>[0]</code>, print information about the gamepad into our gamepad info <code>div</code>, and fire the <code>gameLoop()</code> function that starts the whole ball movement process up.</p> +<pre class="brush: js">window.addEventListener("gamepadconnected", function(e) { + var gp = navigator.getGamepads()[e.gamepad.index]; + gamepadInfo.innerHTML = "Gamepad connected at index " + gp.index + ": " + gp.id + ". It has " + gp.buttons.length + " buttons and " + gp.axes.length + " axes."; + + gameLoop(); +});</pre> +<p>Now we use the {{ domxref("Window.gamepaddisconnected") }} event to check if the gamepad is disconnected again. If so, we stop the {{ domxref("requestAnimationFrame") }} loop (see below) and revert the gamepad information back to what it was originally.</p> +<pre class="brush: js">window.addEventListener("gamepaddisconnected", function(e) { + gamepadInfo.innerHTML = "Waiting for gamepad."; + + rAFStop(start); +});</pre> +<p>Chrome does things differently here. Instead of constantly storing the gamepad's latest state in a variable it only stores a snapshot, so to do the same thing in Chrome you have to keep polling it and then only use the {{ domxref("Gamepad") }} object in code when it is available. We have done this below using {{ domxref("Window.setInterval") }}; once the object is available the gamepad info is outputted, the game loop is started, and the interval is cleared using {{ domxref("Window.clearInterval") }}. Note that in older versions of Chrome {{ domxref("Navigator.getGamepads") }} is implemented with a <code>webkit</code> prefix. We attempt to detect and handle both the prefixed version and the standard version of the function for backwards-compatibility.</p> +<pre class="brush: js">if(!('GamepadEvent' in window)) { + // No gamepad events available, poll instead. + var interval = setInterval(pollGamepads, 500); +} + +function pollGamepads() { + var gamepads = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads : []); + for (var i = 0; i < gamepads.length; i++) { + var gp = gamepads[i]; + if(gp) { + gamepadInfo.innerHTML = "Gamepad connected at index " + gp.index + ": " + gp.id + ". It has " + gp.buttons.length + " buttons and " + gp.axes.length + " axes."; + gameLoop(); + clearInterval(interval); + } + } +}</pre> +<p>Now on to the main game loop. In each execution of the loop we check if one of four buttons is being pressed; if so, we update the values of the <code>a</code> and <code>b</code> movement variables appropriately, then update the {{ cssxref("left") }} and {{ cssxref("top") }} properties, changing their values to the current values of <code>a</code> and <code>b</code> respectively. This has the effect of moving the ball around the screen. In current versions of Chrome (version 34 as of this writing) the button values are stored as an array of double values, instead of {{ domxref("GamepadButton") }} objects. This is fixed in development versions.</p> +<p>After all this is done, we use our <code>rAF</code> variable to request the next animation frame, running <code>gameLoop()</code> again.</p> +<pre class="brush: js">function buttonPressed(b) { +<span class="k"> if</span> <span class="p">(</span><span class="k">typeof</span><span class="p">(</span><span class="nx">b</span><span class="p">)</span> <span class="o">==</span> <span class="s2">"object"</span><span class="p">)</span> <span class="p">{</span> +<span class="nx"> return</span> <span class="nx">b</span><span class="p">.</span><span class="nx">pressed</span><span class="p">;</span> +<span class="nx"> </span><span class="p">}</span> +<span class="p"> return</span> <span class="nx">b</span> <span class="o">==</span> <span class="mf">1.0</span><span class="p">;</span> +} + +function gameLoop() { + var gamepads = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads : []); + if (!gamepads) + return; + + var gp = gamepads[0]; + if (buttonPressed(gp.buttons[0])) { + b--; + } else if (buttonPressed(gp.buttons[2])) { + b++; + } + if(buttonPressed(gp.buttons[1])) { + a++; + } else if(buttonPressed(gp.buttons[3])) { + a--; + } + + ball.style.left = a*2 + "px"; + ball.style.top = b*2 + "px"; + + var start = rAF(gameLoop); +};</pre> +<h3 id="Using_axes_information">Using axes information</h3> +<p><strong>TBD (basically the same, except using axes[i] rather than button[i].value for both Firefox and Chrome.)</strong></p> +<h2 id="Complete_example_Displaying_gamepad_state">Complete example: Displaying gamepad state</h2> +<p>This example shows how to use the {{ domxref("Gamepad") }} object, as well as the {{ domxref("Window.gamepadconnected") }} and {{ domxref("Window.gamepaddisconnected") }} events in order to display the state of all gamepads connected to the system. You can find a <a href="http://luser.github.io/gamepadtest/">working demo</a> and look at the <a href="https://github.com/luser/gamepadtest">full source code</a> on Github.</p> +<pre class="brush: js">var haveEvents = 'GamepadEvent' in window; +var controllers = {}; +var rAF = window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || + window.requestAnimationFrame; + +function connecthandler(e) { + addgamepad(e.gamepad); +} +function addgamepad(gamepad) { + controllers[gamepad.index] = gamepad; var d = document.createElement("div"); + d.setAttribute("id", "controller" + gamepad.index); + var t = document.createElement("h1"); + t.appendChild(document.createTextNode("gamepad: " + gamepad.id)); + d.appendChild(t); + var b = document.createElement("div"); + b.className = "buttons"; + for (var i=0; i<gamepad.buttons.length; i++) { + var e = document.createElement("span"); + e.className = "button"; + //e.id = "b" + i; + e.innerHTML = i; + b.appendChild(e); + } + d.appendChild(b); + var a = document.createElement("div"); + a.className = "axes"; + for (var i=0; i<gamepad.axes.length; i++) { + var e = document.createElement("progress"); + e.className = "axis"; + //e.id = "a" + i; + e.setAttribute("max", "2"); + e.setAttribute("value", "1"); + e.innerHTML = i; + a.appendChild(e); + } + d.appendChild(a); + document.getElementById("start").style.display = "none"; + document.body.appendChild(d); + rAF(updateStatus); +} + +function disconnecthandler(e) { + removegamepad(e.gamepad); +} + +function removegamepad(gamepad) { + var d = document.getElementById("controller" + gamepad.index); + document.body.removeChild(d); + delete controllers[gamepad.index]; +} + +function updateStatus() { + if (!haveEvents) { + scangamepads(); + } + for (j in controllers) { + var controller = controllers[j]; + var d = document.getElementById("controller" + j); + var buttons = d.getElementsByClassName("button"); + for (var i=0; i<controller.buttons.length; i++) { + var b = buttons[i]; + var val = controller.buttons[i]; + var pressed = val == 1.0; + if (typeof(val) == "object") { + pressed = val.pressed; + val = val.value; + } + var pct = Math.round(val * 100) + "%" + b.style.backgroundSize = pct + " " + pct; + if (pressed) { + b.className = "button pressed"; + } else { + b.className = "button"; + } + } + + var axes = d.getElementsByClassName("axis"); + for (var i=0; i<controller.axes.length; i++) { + var a = axes[i]; + a.innerHTML = i + ": " + controller.axes[i].toFixed(4); + a.setAttribute("value", controller.axes[i] + 1); + } + } + rAF(updateStatus); +} + +function scangamepads() { + var gamepads = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : []); + for (var i = 0; i < gamepads.length; i++) { + if (gamepads[i]) { + if (!(gamepads[i].index in controllers)) { + addgamepad(gamepads[i]); + } else { + controllers[gamepads[i].index] = gamepads[i]; + } + } + } +} + +window.addEventListener("gamepadconnected", connecthandler); +window.addEventListener("gamepaddisconnected", disconnecthandler); +if (!haveEvents) { + setInterval(scangamepads, 500); +}</pre> +<h2 id="Specifications">Specifications</h2> +<p>{{page("/en-US/docs/Gamepad","Specifications")}}</p> +<h2 id="Browser_compatibility">Browser compatibility</h2> +<p>{{page("/en-US/docs/Gamepad","Browser_compatibility")}}</p> +<p> </p> +<p> </p> +<p> </p> diff --git a/files/fr/web/guide/api/index.html b/files/fr/web/guide/api/index.html new file mode 100644 index 0000000000..9dbd8867c5 --- /dev/null +++ b/files/fr/web/guide/api/index.html @@ -0,0 +1,24 @@ +--- +title: Guide to Web APIs +slug: Web/Guide/API +tags: + - API + - Guide + - Landing + - Web +translation_of: Web/Guide/API +--- +<p>Le Web peut être utilisé avec de nombreuses API, accessibles en JavaScript, qui permettent de construire des applications puissantes, sur le Web, localement ou sur un serveur grâce à <a href="https://nodejs.org/">Node.js</a>. Sur cette page, vous pourrez trouver une liste complète de l'ensemble des API utilisables avec les technologies web.</p> + +<h2 id="Index_des_API_Web_(A_à_Z)">Index des API Web (A à Z)</h2> + +<p>{{ListGroups}}</p> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li><a href="/fr/docs/Web/API">Référence des interfaces des API Web </a>(un index de l'ensemble des interfaces qui composent ces API)</li> + <li><a href="/fr/docs/Web/API/Document_Object_Model">Le <em>Document Object Model</em></a> (DOM ou modèle objet de document)</li> + <li><a href="/fr/docs/Web/Events">Référence des évènements associés aux API Web</a></li> + <li><a href="/fr/docs/Apprendre">Apprendre le développement web</a></li> +</ul> diff --git a/files/fr/web/guide/api/webrtc/index.html b/files/fr/web/guide/api/webrtc/index.html new file mode 100644 index 0000000000..158b7395a5 --- /dev/null +++ b/files/fr/web/guide/api/webrtc/index.html @@ -0,0 +1,51 @@ +--- +title: WebRTC +slug: Web/Guide/API/WebRTC +tags: + - Intro + - WebRTC +translation_of: Web/API/WebRTC_API +--- +<p><strong>WebRTC</strong> (où RTC signifie Real-Time Communications -Communications en temps réel-) est une technologie qui permet la transmission en continue (streaming) de l'audio/vidéo et le partage de données entre les navigateurs clients (peers). Comme un ensemble de normes (standards), le WebRTC fournit à n'importe quel navigateur la capacité de partager des données d'application et d'effectuer des téléconférences d’égal à égal, sans avoir à installer quelques plug-ins ou logiciels tiers.</p> +<p>Les composants WebRTC sont accessibles grâce aux APIs JavaScript : l'API de flux réseau (Network Stream), qui représente un flux de données audio ou vidéo ; l'API de Connexion (PeerConnection), qui permet à plusieurs utilisateurs de communiquer via leurs navigateurs ; et l'API DataChannel qui permet la communication d'autres types de données pour le jeu en temps réel, dialogue en ligne, transfert de fichiers, etc.</p> +<div class="note"> + <p><strong>Note:</strong> Cette documentation n'est pas à jour et est un travail en cours. <strong>Vous voulez aider?</strong> Nous avons besoin de personnes pour parcourir ces docs et les mettre à jour, tout autant que de documenter les APIs dans notre référence d’API! Consultez notre guide à la page <a href="/fr/docs/MDN/Débuter_sur_MDN">Débuter sur MDN</a> si vous voulez aider.</p> +</div> +<h2 id="Guide">Guide</h2> +<dl> + <dt> + <a href="/fr/docs/WebRTC/Introduction" title="/fr/docs/WebRTC/Introduction">Introduction au WebRTC</a></dt> + <dd> + Guide d'introduction à ce qu’est WebRTC et comment ça marche.</dd> + <dt> + <a href="/fr/docs/WebRTC/communication-de-pair-a-pair-avec-WebRTC" title="Communication de pair-à-pair avec WebRTC">Communications Peer-to-peer avec WebRTC</a></dt> + <dd> + Comment faire pour effectuer des communications peer-to-peer en utilisant les APIs WebRTC.</dd> + <dt> + <a href="/fr/docs/WebRTC/Prendre_des_photos_avec_la_webcam" title="Prendre des photos avec la webcam">Prendre des photos avec la webcam</a></dt> + <dd> + Un guide d'introduction à ce qu’est WebRTC et à comment ça marche.</dd> + <dt> + <a href="/fr/docs/Web/Guide/API/WebRTC/WebRTC_architecture" title="/fr/docs/Web/Guide/API/WebRTC/WebRTC_architecture">Introduction à l'architecture WebRTC</a></dt> + <dd> + <strong>(AKA "WebRTC et l'océan des acronymes")</strong> WebRTC a beaucoup de parties différentes et cela peut être accablant et source de confusion pour les nouveaux venus. Cet article a pour but d'expliquer qu’elles sont toutes les pièces, et comment elles s'imbriquent.</dd> + <dt> + <a href="/fr/docs/Web/Guide/API/WebRTC/WebRTC_basics" title="/fr/docs/Web/Guide/API/WebRTC/WebRTC_basics">L’essentiel du WebRTC</a></dt> + <dd> + Maintenant que vous comprenez l'architecture WebRTC, vous pouvez passer à cet article, qui vous emmène à travers la création d'une application multi-navigateur RTC simple.</dd> +</dl> +<h2 id="Référence">Référence</h2> +<dl> + <dt> + <a href="/fr/docs/Web/API/Navigator.getUserMedia">Navigator.getUserMedia</a></dt> + <dd> + L'API pour capturer des médias (audio/video).</dd> + <dt> + <a href="/fr/docs/Web/API/RTCPeerConnection">RTCPeerConnection</a></dt> + <dd> + L'interface traitant en continu des données entre deux pairs.</dd> + <dt> + <a href="/fr/docs/Web/API/RTCDataChannel">RTCDataChannel</a></dt> + <dd> + L'interface pour l'envoi des données arbitraires à travers la connexion de pair (peer connection).</dd> +</dl> diff --git a/files/fr/web/guide/api/webrtc/webrtc_architecture/index.html b/files/fr/web/guide/api/webrtc/webrtc_architecture/index.html new file mode 100644 index 0000000000..8b512d7127 --- /dev/null +++ b/files/fr/web/guide/api/webrtc/webrtc_architecture/index.html @@ -0,0 +1,54 @@ +--- +title: Introduction à l'architecture WebRTC +slug: Web/Guide/API/WebRTC/WebRTC_architecture +tags: + - WebRTC +translation_of: Web/API/WebRTC_API/Connectivity +--- +<p class="summary">(AKA "WebRTC et l'océan des acronymes") WebRTC comporte de nombreuses parties distinctes et cela peut être accablant et source de confusion pour les nouveaux venus. Cet article a pour but d'expliquer quelles sont toutes ses parties, et comment elles s'imbriquent.</p> + +<h2 id="Qu’est-ce_que_ICE">Qu’est-ce que ICE?</h2> + +<p><a href="http://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment">Interactive Connectivity Establishment (ICE)</a> est un cadre qui permet à votre navigateur web de se connecter avec des pairs. Il y a plusieurs raisons pour qu’une connexion directe entre un pair A et un pair B ne fonctionne pas. Il a besoin de contourner les pare-feux qui pourraient empêcher la connexion de s’ouvrir, il doit vous attribuer une adresse unique si votre appareil n'a pas une adresse IP publique comme la plupart du temps et transmettre des données via un serveur si votre routeur ne permet pas de vous connecter directement avec des pairs. ICE utilise certaines des techniques suivantes décrites ci-dessous pour y parvenir :</p> + +<h2 id="Qu’est-ce_que_STUN">Qu’est-ce que STUN?</h2> + +<p><a href="http://fr.wikipedia.org/wiki/Simple_Traversal_of_UDP_through_NATs">Session Traversal Utilities for NAT (STUN)</a> (acronyme dans un acronyme) est un protocole qui permet de découvrir votre adresse publique et de déterminer toute restriction dans votre routeur qui empêcherait une connexion directe avec un pair.</p> + +<p>Le client enverra une demande à un serveur STUN sur internet qui répondra avec l'adresse du client public et informera si le client est accessible derrière un routeur NAT.</p> + +<p><img alt="An interaction between two users of a WebRTC application involving a STUN server." src="https://mdn.mozillademos.org/files/6115/webrtc-stun.png" style="display: block; height: 378px; margin: 0px auto; width: 259px;"></p> + +<h2 id="Qu’est-ce_que_NAT">Qu’est-ce que NAT?</h2> + +<p><a href="http://fr.wikipedia.org/wiki/Network_address_translation">Network Address Translation (NAT)</a> est utilisé pour donner à votre appareil une adresse IP publique. Un routeur aura une adresse IP publique et chaque périphérique connecté au routeur aura une adresse IP privée. Les demandes seront traduites de l'adresse IP privée de l'appareil vers l'IP publique du routeur avec un port unique. De cette façon, vous n'avez pas besoin d’avoir une adresse IP publique unique pour chaque périphérique, mais pouvez encore être découvert sur internet.</p> + +<p>Certains routeurs auront des restrictions sur ceux qui peuvent se connecter aux dispositifs sur le réseau. Cela peut signifier que, même si nous avons l'adresse IP publique, trouvée par le serveur STUN, tout le monde ne peut pas créer une connexion. Dans ce cas, il faut se tourner vers le TURN.</p> + +<h2 id="Qu’est-ce_que_TURN">Qu’est-ce que TURN?</h2> + +<p>Certains routeurs utilisant NAT emploient une restriction appelée ‘Symmetric NAT’. Cela signifie que le routeur n'accepte que les connexions de pairs auxquelles vous vous êtes déjà connecté.</p> + +<p><a href="http://en.wikipedia.org/wiki/TURN">Traversal Using Relays around NAT (TURN)</a> Doit contourner la restriction de NAT Symétrique en ouvrant une connexion avec un serveur TURN et retransmettre toutes les informations par le biais de ce serveur. Vous devrez créer une connexion avec un serveur TURN et dire à tous les pairs d'envoyer des paquets au serveur qui vous seront alors expédiés. Cela vient évidemment avec une certaine surcharge et n'est donc utilisé que s'il n'y a pas d'autres alternatives.</p> + +<p><img alt="Une interaction entre deux utilisateurs d'une application WebRTC impliquant des serveurs STUN et TURN." src="https://mdn.mozillademos.org/files/6117/webrtc-turn.png" style="display: block; height: 297px; margin: 0px auto; width: 295px;"></p> + +<h2 id="Qu’est-ce_que_SDP">Qu’est-ce que SDP?</h2> + +<p><a href="http://en.wikipedia.org/wiki/Session_Description_Protocol">Session Description Protocol (SDP)</a> est une norme décrivant le contenu multimédia de la connexion comprenant la résolution, les formats, les codecs, le cryptage, etc., afin que les deux pairs puissent se comprendre une fois le transfert des données en cours. Ce n'est pas le média lui-même, mais plus les métadonnées.</p> + +<h2 id="Qu’est-ce_qu'une_OffreRéponse_et_un_Canal_de_Signal">Qu’est-ce qu'une Offre/Réponse et un Canal de Signal?</h2> + +<p>Malheureusement WebRTC ne peut pas créer de connexions sans une sorte de serveur au milieu. Nous appelons cela le Canal de Signal (Signal Channel). C'est une sorte de canal de communication pour échanger des informations avant de configurer une connexion, que ce soit par e-mail, carte postale ou pigeon voyageur... C’est comme bon vous semble.</p> + +<p>L’information que nous avons besoin d'échanger est l'Offre et la Réponse qui contient juste le SDP mentionné ci-dessus.</p> + +<p>Le pair A, qui sera l'initiateur de la connexion, va créer une offre. Il enverra ensuite cette offre au pair B en utilisant le Canal de Signal choisi. Le pair B recevra l’offre du Canal de Signal et créera la Réponse. Il renverra ensuite tout ceci au pair A via le Canal de Signal.</p> + +<h2 id="Qu’est-ce_qu’un_candidat_ICE">Qu’est-ce qu’un candidat ICE?</h2> + +<p>Autant que d'échanger des informations sur les médias (cf. Offre/Réponse et SDP), les pairs doivent échanger des informations sur la connexion réseau. Ceci est connu comme étant un candidat ICE et détaille les méthodes disponibles que le pair est en mesure de communiquer (directement ou via un serveur TURN).</p> + +<h2 id="L'échange_entier_dans_un_diagramme_compliqué">L'échange entier dans un diagramme compliqué</h2> + +<p><a href="https://hacks.mozilla.org/wp-content/uploads/2013/07/webrtc-complete-diagram.png"><img alt="Un schéma architectural complet montrant l'ensemble du processus WebRTC." src="https://mdn.mozillademos.org/files/6119/webrtc-complete-diagram.png" style="display: block; height: 559px; margin: 0px auto; width: 641px;"></a></p> diff --git a/files/fr/web/guide/api/webrtc/webrtc_basics/index.html b/files/fr/web/guide/api/webrtc/webrtc_basics/index.html new file mode 100644 index 0000000000..f114e2957f --- /dev/null +++ b/files/fr/web/guide/api/webrtc/webrtc_basics/index.html @@ -0,0 +1,359 @@ +--- +title: L’essentiel du WebRTC +slug: Web/Guide/API/WebRTC/WebRTC_basics +tags: + - WebRTC +translation_of: Web/API/WebRTC_API/Signaling_and_video_calling +--- +<div class="summary"> +<p>Maintenant que vous comprenez l'<a href="/fr/docs/Web/Guide/API/WebRTC/WebRTC_architecture" title="Introduction à l'architecture WebRTC">architecture WebRTC</a>, vous pouvez passer à cet article, qui vous emmène à travers la création d'une application RTC multi-navigateurs.A la fin de cet article vous devriez pouvoir créer un canal de données et de médias pair à pair qui fonctionne</p> +</div> + +<h2 id="Contenu_semi-ancien_à_partir_de_RTCPeerConnection">Contenu semi-ancien, à partir de RTCPeerConnection</h2> + +<p>Les informations ci-dessous proviennent de RTCPeerConnection; elles pourraient rester ici, comme aller ailleurs. Mais elles ne font pas partie de cette page. Alors pendant que je trie cette page, elles seront ici, jusqu'à ce que je sache où elles appartiennent pour de vrai.</p> + +<h2 id="Usage_basique">Usage basique</h2> + +<p>l'utilisation de RTCPeerConnection implique la négociation d'une connexion entre votre machine et une machine distante,et ce, en générant {{interwiki("wikipedia", "Session Description Protocol")}} a échanger entre les deux. L'appelant commence le processus en envoyant une offre à l'appareil distant, qui répond par l'acceptation ou le rejet de la demande de connexion.</p> + +<p>Les deux parties (l'appelant et l'appelé) doivent mettre en place leurs propres instances de RTCPeerConnection pour représenter leurs extrémités de la connexion peer-to-peer:</p> + +<pre class="notranslate"><code>var pc = new RTCPeerConnection(); +pc.onaddstream = function(obj) { + var vid = document.createElement("video"); + document.appendChild(vid); + vid.srcObject = obj.stream; +} + +// Helper functions +function endCall() { + var videos = document.getElementsByTagName("video"); + for (var i = 0; i < videos.length; i++) { + videos[i].pause(); + } + + pc.close(); +} + +function error(err) { + endCall(); +}</code></pre> + +<p><strong>Initialiser un appel</strong></p> + +<p>l'appelant doit utiliser {{domxref("navigator.getUserMedia()")}} pour obtenir un flux vidéo, puis ajouter ce flux à l'instance de RTCPeerConnection. Une fois que cela a été fait, il doit appeler {{domxref("RTCPeerConnection.createOffer()")}} pour créer une offre,puis la configurer et l'envoyer a un serveur faisant office d'intermediaire.</p> + +<pre class="notranslate"><code>// recuperer la liste des "amis" a partir du serveur +// l'utilisateur selectionne un amis avec qui lancer la connection +navigator.getUserMedia({video: true}, function(stream) { + // l'ajout d'un stream locale ne declanche pas onaddstream, + // donc il faut l'appeler manuellement. + pc.onaddstream = e => video.src = URL.createObjectURL(e.stream); + pc.addStream(stream); + + pc.createOffer(function(offer) { + pc.setLocalDescription(offer, function() { + // envoi de l'offre au serveur qui se charge de la transmettre a "l'ami" choisit precedemment. + }, error); + }, error); +});</code></pre> + +<p><strong>Répondre à un appel</strong></p> + +<p>sur l'autre machine, l'ami recevra l'offre à partir du serveur en utilisant le protocole approprié (définit par le serveur). Une fois que l'offre arrive,{{domxref("navigator.getUserMedia()")}} est une fois de plus appelée pour créer le second flux, qui est ajouté à la RTCPeerConnection. Un objet {{domxref("RTCSessionDescription")}} est créé, et mis en place comme la description du distant en appelant {{domxref("RTCPeerConnection.setRemoteDescription()")}}.</p> + +<p>Ensuite, une réponse est créée en utilisant {{domxref("RTCPeerConnection.createAnswer()")}} et renvoyé au serveur, qui la transmet à l'appelant.</p> + +<pre class="notranslate"><code>var offer = getOfferFromFriend(); +navigator.getUserMedia({video: true}, function(stream) { + pc.onaddstream = e => video.src = URL.createObjectURL(e.stream); + pc.addStream(stream); + + pc.setRemoteDescription(new RTCSessionDescription(offer), function() { + pc.createAnswer(function(answer) { + pc.setLocalDescription(answer, function() { + // envoi de la réponse au serveur qui la transmettra a l'appelant + }, error); + }, error); + }, error); +});</code></pre> + +<p><strong>Gestion de la réponse</strong></p> + +<p>retour a la première machine, qui recois la reponse. une fois cette dernière arrivée,l'appelant utilise {{domxref("RTCPeerConnection.setRemoteDescription()")}} pour définir la réponse comme la description de l'autre l'extrémité de la connexion. </p> + +<pre class="notranslate"><code>// pc a été déclaré </code>précédemment<code>, lors de l'envoi de l'offre. +var offer = getResponseFromFriend(); +pc.setRemoteDescription(new RTCSessionDescription(offer), function() { }, error);</code></pre> + +<h2 id="Ancien_contenu_en_approche!">Ancien contenu en approche!</h2> + +<p>Tout ce qui est en dessous de ce point est potentiellement obsolète. Il est toujours là en attente d'examen et d'intégration possible dans d'autres parties de la documentation où il serait encore valides.</p> + +<div class="note"> +<p>Ne pas utiliser les examples de cette page. Voir l'article <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Signaling_and_video_calling">signalisation et appel vidéo</a> ,pour des example mis a jour sur l'utilisation des medias WebRTC.</p> +</div> + +<h2 id="Note">Note</h2> + +<p>Cette page contient des informations périmées selon <a href="http://stackoverflow.com/a/25065359/3760500">http://stackoverflow.com/a/25065359/3760500</a></p> + +<blockquote> +<p>Peu importe ce que la page de MDN indique, RTPDataChannels est très désuet (faites connaître l'URL). Firefox et Chrome supportent les spec DataChannels maintenant. Idem pour DTLSSRTPKeyAgreement je pense.</p> +</blockquote> + +<h2 id="Shims_Bibliothèque_d’interception_d’API">Shims (Bibliothèque d’interception d’API)</h2> + +<p>Comme vous pouvez l'imaginer, avec une API aussi jeune, vous devez utiliser les préfixes de navigateur et les positionner dans des variables communes.</p> + +<pre class="brush: js notranslate">var PeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; +var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate; +var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; +navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;</pre> + +<h2 id="PeerConnection">PeerConnection</h2> + +<p>C'est le point de départ pour créer une connexion avec un pair. Il accepte des options de configuration sur les serveurs ICE à utiliser pour établir une connexion.</p> + +<pre class="brush: js notranslate">var pc = new PeerConnection(configuration, options);</pre> + +<h3 id="RTCConfiguration"><strong><code>RTCConfiguration</code></strong></h3> + +<p>L'objet {{domxref("RTCConfiguration")}} contient l’information sur les serveurs TURN et/ou STUN à utiliser pour ICE. Ceci est requis pour s'assurer que la plupart des utilisateurs peuvent en fait créer une connexion en évitant les restrictions du NAT et du pare-feu.</p> + +<pre class="brush: js notranslate">var configuration = { + iceServers: [ + {url: "stun:23.21.150.121"}, + {url: "stun:stun.l.google.com:19302"}, + {url: "turn:numb.viagenie.ca", credential: "webrtcdemo", username: "louis%40mozilla.com"} + ] +}</pre> + +<p>Google met à disposition un <a href="https://code.google.com/p/natvpn/source/browse/trunk/stun_server_list">serveur STUN public</a> que nous pouvons utiliser. J'ai également créé un compte chez http://numb.viagenie.ca/ pour un accès gratuit à un serveur TURN. Vous pouvez faire la même chose et les remplacer par vos propres informations d'identification.</p> + +<h3 id="options_Cf._Note_avant"><strong><code>options</code></strong> (Cf. "Note" avant)</h3> + +<p>Selon le type de connexion, vous devez passer des options.</p> + +<pre class="brush: js notranslate" lang="javascript">var options = { + optional: [ + {DtlsSrtpKeyAgreement: true}, + {RtpDataChannels: true} + ] +}</pre> + +<p><code>DtlsSrtpKeyAgreement</code> est exigé pour Chrome et Firefox pour interagir.</p> + +<p><code>RtpDataChannels</code> est nécessaire si nous voulons utiliser l'API DataChannels sur Firefox.</p> + +<h2 id="ICECandidate">ICECandidate</h2> + +<p>Après avoir créé la connexion et en passant par les serveurs STUN et TURN disponibles, un événement sera déclenché une fois que le framework ICE aura trouvé certains « candidats » qui permettront de vous connecter avec un pair. Ceci est reconnu comme étant un candidat ICE et exécute une fonction de rappel sur PeerConnection#onicecandidate.</p> + +<pre class="brush: js notranslate" lang="javascript">pc.onicecandidate = function (e) { + // candidate exists in e.candidate + if (e.candidate == null) { return } + send("icecandidate", JSON.stringify(e.candidate)); + pc.onicecandidate = null; +};</pre> + +<p>Lorsque le rappel est exécuté, nous devons utiliser le canal de signal pour envoyer le Candidat au pair. Sur Chrome, on trouve habituellement plusieurs candidats ICE, nous n’en avons besoin que d'un seul donc j'en envoie généralement une puis supprimer le descripteur. Firefox inclut le Candidat dans l'Offre SDP.</p> + +<h2 id="Canal_de_Signal">Canal de Signal</h2> + +<p>Maintenant que nous avons un candidat ICE, nous devons l’envoyer à nos pairs afin qu'ils sachent comment se connecter avec nous. Toutefois, cela nous laisse face à une problématique de l’œuf et de la poule; Nous voulons que PeerConnection envoie des données à un pair, mais avant cela, nous devons lui envoyer des métadonnées…</p> + +<p>C'est là qu'intervient le canal de signal. C'est n'importe quel mode de transport de données qui permet aux deux pairs d’échanger des informations. Dans cet article, nous allons utiliser <a href="http://firebase.com">FireBase</a> parce que c'est incroyablement facile à installer et ne nécessite aucun hébergement ou code serveur.</p> + +<p>Pour l'instant imaginez seulement que deux méthodes existent: <code>send()</code> va prendre une clé et lui affecter des données et <code>recv()</code> appelle un descripteur lorsqu'une clé a une valeur.</p> + +<p>La structure de la base de données ressemble à ceci :</p> + +<pre class="brush: js notranslate" lang="json">{ + "": { + "candidate:": … + "offer": … + "answer": … + } +}</pre> + +<p>Les connexions sont divisées par un <code>roomId</code> et stockeront 4 éléments d'information, le candidat ICE de l'auteur de l'offre, le candidat ICE du répondeur, l'offre SDP et la réponse SDP.</p> + +<h2 id="Offre">Offre</h2> + +<p>Une offre SDP (Session Description Protocol) et le méta données qui décrit aux autres pairs le format attendu(video, formats, codecs, cryptage, résolution, taille, etc etc).</p> + +<p>Un échange nécessite une offre d'un pair, alors l'autre pair doit recevoir l'offre et offrir en retour une réponse.</p> + +<pre class="brush: js notranslate" lang="javascript">pc.createOffer(function (offer) { + pc.setLocalDescription(offer); + + send("offer", JSON.stringify(offer)); +}, errorHandler, constraints);</pre> + +<h3 id="errorHandler"><strong><code>errorHandler</code></strong></h3> + +<p>S'il y avait un problème lors de la génération d’une offre, cette méthode sera exécutée avec les détails de l'erreur comme premier argument.</p> + +<pre class="brush: js notranslate" lang="javascript">var errorHandler = function (err) { + console.error(err); +};</pre> + +<h3 id="constraints"><strong><code>constraints</code></strong></h3> + +<p>Options pour l'offre SDP.</p> + +<pre class="brush: js notranslate" lang="javascript">var constraints = { + mandatory: { + OfferToReceiveAudio: true, + OfferToReceiveVideo: true + } +};</pre> + +<p><code>OfferToReceiveAudio/Video</code> Dit aux autres pair que vous désirez recevoir de la vidéo ou de l'audio de leur part. Ce n'est pas nécessaire pour DataChannels.</p> + +<p>Une fois que l'offre a été générée nous devons définir le SDP local à la nouvelle offre et l’envoyer par le canal de signal aux autres pairs et attendre leur réponse SDP.</p> + +<h2 id="Réponse">Réponse</h2> + +<p>Une réponse SDP est comme une offre, mais est une réponse ; un peu comme répondre au téléphone. Nous pouvons seulement émettre une réponse qu’après avoir reçu une offre.</p> + +<pre class="brush: js notranslate" lang="javascript">recv("offer", function (offer) { + offer = new SessionDescription(JSON.parse(offer)) + pc.setRemoteDescription(offer); + + pc.createAnswer(function (answer) { + pc.setLocalDescription(answer); + + send("answer", JSON.stringify(answer)); + }, errorHandler, constraints); +});</pre> + +<h2 id="DataChannel">DataChannel</h2> + +<p>J'expliquerai d'abord comment utiliser PeerConnection pour l'API DataChannels et le transfert de données arbitraires entre des pairs.</p> + +<p><em>Note: Au moment de l’écriture de cet article, l'interopérabilité entre Chrome et Firefox n'est pas possible avec DataChannels. Chrome prend en charge un protocole similaire mais privé et soutiendra le protocole standard bientôt.</em></p> + +<pre class="brush: js notranslate" lang="javascript">var channel = pc.createDataChannel(channelName, channelOptions);</pre> + +<p>L'auteur de l'offre doit être le pair qui crée le canal. Le répondeur recevra le canal dans le rappel (callback) <code>ondatachannel</code> dans le PeerConnection. Vous devez appeler <code>createDataChannel()</code> une fois avant de créer l'offre.</p> + +<h3 id="channelName"><strong><code>channelName</code></strong></h3> + +<p>Il s'agit d'une chaîne qui agit comme une étiquette pour le nom de votre canal. <em>AVERTISSEMENT : Assurez-vous que votre nom de canal n'a pas d'espaces ou Chrome va échouer sur <code>createAnswer()</code>.</em></p> + +<h3 id="channelOptions"><strong><code>channelOptions</code></strong></h3> + +<pre class="brush: js notranslate" lang="javascript">var channelOptions = {};</pre> + +<p>Ces options ne sont pas bien supportées sur Chrome donc vous pouvez laisser ça vide pour l'instant. Vérifiez le <a href="http://dev.w3.org/2011/webrtc/editor/webrtc.html#attributes-7">RFC</a> pour plus d'informations sur les options.</p> + +<h3 id="Méthodes_et_événements_de_canal">Méthodes et événements de canal</h3> + +<h4 id="onopen"><strong><code>onopen</code></strong></h4> + +<p>Exécuté lorsque la connexion est établie.</p> + +<h4 id="onerror"><strong><code>onerror</code></strong></h4> + +<p>Exécuté s'il y a une erreur de création de la connexion. Le premier argument est un objet d'erreur.</p> + +<pre class="brush: js notranslate" lang="javascript">channel.onerror = function (err) { + console.error("Channel Error:", err); +};</pre> + +<h4 id="onmessage"><strong><code>onmessage</code></strong></h4> + +<pre class="brush: js notranslate" lang="javascript">channel.onmessage = function (e) { + console.log("Got message:", e.data); +}</pre> + +<p>Le cœur de la connexion. Lorsque vous recevez un message, cette méthode s’exécute. Le premier argument est un objet d'événement qui contient les données, heure de réception et autres informations.</p> + +<h4 id="onclose"><strong><code>onclose</code></strong></h4> + +<p>Exécuté si l'autre pair ferme la connexion.</p> + +<h3 id="Lier_les_événements"><strong>Lier les événements</strong></h3> + +<p>Si vous êtes le créateur du canal(l'auteur de l'offre), vous pouvez lier des événements directement à la DataChannel que vous avez créé avec <code>createChannel</code>. Si vous êtes l'auteur de la réponse, vous devez utiliser le callback <code>ondatachannel</code> dans le PeerConnection afin d'accéder au même canal.</p> + +<pre class="brush: js notranslate" lang="javascript">pc.ondatachannel = function (e) { + e.channel.onmessage = function () { … }; +};</pre> + +<p>Le canal est disponible dans l’objet événement passé dans le descripteur en tant que <code>e.channel</code>.</p> + +<h4 id="send"><strong><code>send()</code></strong></h4> + +<pre class="brush: js notranslate" lang="javascript">channel.send("Hi Peer!");</pre> + +<p>Cette méthode vous permet d'envoyer des données directement au pair! Incroyable. Vous devez envoyer un String, Blob, ArrayBuffer ou ArrayBufferView, alors assurez-vous de "stringifier" les objets.</p> + +<h4 id="close"><strong><code>close()</code></strong></h4> + +<p>Ferme le canal une fois que la connexion doit se terminer. Il est recommandé de le faire sur l’ unload de la page.</p> + +<h2 id="Media">Media</h2> + +<p>Maintenant nous allons couvrir la transmission de médias tels que l'audio ou la vidéo. Pour afficher la vidéo et l'audio, vous devez inclure un tag <code><video></code> dans le document avec l'attribut <code>autoplay</code>.</p> + +<h3 id="Obtenir_les_médias_de_lutilisateur">Obtenir les médias de l'utilisateur</h3> + +<pre class="brush: js notranslate"><video id="preview" autoplay></video> + +var video = document.getElementById("preview"); +navigator.getUserMedia(mediaOptions, function (stream) { + video.src = URL.createObjectURL(stream); +}, errorHandler);</pre> + +<p><strong><code>mediaOptions</code></strong></p> + +<p>Les contraintes sur les types de médias que vous souhaitez renvoyer de l'utilisateur.</p> + +<pre class="brush: js notranslate" lang="javascript">var mediaOptions = { + video: true, + audio: true +};</pre> + +<p>Si vous voulez juste une conversation audio, supprimez la clé <code>video</code>.</p> + +<h4 id="errorHandler_2"><strong><code>errorHandler</code></strong></h4> + +<p>Exécuté s'il y a une erreur retournée par le support demandé.</p> + +<h3 id="Événements_Médias_et_Méthodes">Événements Médias et Méthodes</h3> + +<h4 id="addStream"><strong><code>addStream</code></strong></h4> + +<p>Ajoute le flux de <code>getUserMedia</code> au PeerConnection.</p> + +<pre class="brush: js notranslate" lang="javascript">pc.addStream(stream);</pre> + +<h4 id="onaddstream"><strong><code>onaddstream</code></strong></h4> + +<pre class="brush: js notranslate"><video id="otherPeer" autoplay></video> + +var otherPeer = document.getElementById("otherPeer"); +pc.onaddstream = function (e) { + otherPeer.src = URL.createObjectURL(e.stream); +};</pre> + +<p>Exécuté lorsque la connexion a été mise en place et que l'autre pair a ajouté le flux de données pour la connexion avec <code>addStream</code>. Vous avez besoin d'un autre tag <code><video></code> pour afficher les médias de l'autre pair.</p> + +<p>Le premier argument est un objet d'événement avec les flux de média de l'autre pair.</p> + +<h2 id="Afficher_la_Source">Afficher la Source</h2> + +<p>Vous pouvez voir la source développée à partir de tous les extraits de code de cet article à <a href="http://github.com/louisstow/WebRTC">mon repo WebRTC</a>.</p> + +<ul> + <li> + <p><strong>Exemple de DataChannels :</strong> <a href="https://github.com/louisstow/WebRTC/blob/master/datachannels.html">code</a>, <a href="http://louisstow.github.io/WebRTC/datachannels.html">demo</a></p> + </li> + <li> + <p><strong>Exemple de média :</strong> <a href="https://github.com/louisstow/WebRTC/blob/master/media.html">code</a>, <a href="http://louisstow.github.io/WebRTC/media.html">demo</a></p> + </li> +</ul> diff --git a/files/fr/web/guide/audio_and_video_delivery/buffering_seeking_time_ranges/index.html b/files/fr/web/guide/audio_and_video_delivery/buffering_seeking_time_ranges/index.html new file mode 100644 index 0000000000..89be1e7ca4 --- /dev/null +++ b/files/fr/web/guide/audio_and_video_delivery/buffering_seeking_time_ranges/index.html @@ -0,0 +1,218 @@ +--- +title: 'Mémoire tampon, position, et plages de temps' +slug: Web/Guide/Audio_and_video_delivery/buffering_seeking_time_ranges +tags: + - Apps + - Buffer + - HTML5 + - TimeRanges + - Video + - buffering + - seeking +translation_of: Web/Guide/Audio_and_video_delivery/buffering_seeking_time_ranges +--- +<div class="summary"> +<p><span class="seoSummary">Il est parfois utile de savoir combien d'{{htmlelement("audio") }} ou {{htmlelement("video") }} a été téléchargé ou peut être joué sans délai — par exemple pour afficher la barre de progression du tampon dans un lecteur audio ou vidéo. Cet article explique comment construire une barre de progrès de mise en mémoire tampon en utilisant <a href="/fr/docs/Web/API/TimeRanges">TimeRanges</a>, et d'autres fonctionnalités de l'API Media.</span></p> +</div> + +<h2 id="Buffered">Buffered</h2> + +<p>L'attribut <code>buffered</code> indique quelles parties du média ont été téléchargées. Il retourne un objet {{ domxref("TimeRanges") }}, qui indique tous les morceaux téléchargés. C'est généralement contigu, mais si l'utilisateur saute à une autre position pendant que le média est en cours de chargement, il peut alors y avoir des trous.</p> + +<p>Cela fonctionne avec {{htmlelement("audio") }} et {{htmlelement("video") }}; pour l'instant, considérons un simple exemple audio:</p> + +<pre class="brush: html"><audio id="my-audio" controls src="music.mp3"> +</audio></pre> + +<p>On accède à cet attribut ainsi:</p> + +<pre class="brush: js">var myAudio = document.getElementById('my-audio'); + +var bufferedTimeRanges = myAudio.buffered;</pre> + +<h2 id="Objet_TimeRanges">Objet TimeRanges</h2> + +<p>TimeRanges est une série de plages de temps ne se chevauchant pas, avec un temps de début et de fin. (<a href="/fr/docs/Web/API/TimeRanges">en savoir plus sur TimeRanges</a>).</p> + +<p>Un objet {{ domxref("TimeRanges") }} contient les propriétés/méthodes suivantes:</p> + +<ul> + <li><code>length</code>: Le nombre de plages de temps contenus dans l'objet.</li> + <li><code>start(index)</code>: Permet de récupérer le temps du début, en seconde, d'une plage de temps.</li> + <li><code>end(index)</code>: Permet de récupérer le temps de la fin, en seconde, d'une plage de temps.</li> +</ul> + +<p>Sans interraction utilisateur il y a généralement une seule plage de temps, mais si vous sautez dans le média alors plus d'une plage de temps peut apparaître, comme illustré dans la visualisation ci-dessous. Elle représente deux plages de temps en mémoire tampon — une qui s'étend de 0 à 5 secondes et la seconde qui s'étend de 15 à 19 secondes.</p> + +<pre>------------------------------------------------------ +|=============| |===========| | +------------------------------------------------------ +0 5 15 19 21</pre> + +<p>Pour cette instance audio, l'objet {{ domxref("TimeRanges") }} associé aurait les propriétés suivantes:</p> + +<pre class="brush: js">myAudio.buffered.length; // returns 2 +myAudio.buffered.start(0); // returns 0 +myAudio.buffered.end(0); // returns 5 +myAudio.buffered.start(1); // returns 15 +myAudio.buffered.end(1); // returns 19</pre> + +<p>Pour essayer et visualiser les plages de temps en mémoire tampon, on peut écrire un peu d'HTML:</p> + +<pre class="brush: html"><p> + <audio id="my-audio" controls> + <source src="music.mp3" type="audio/mpeg"> + </audio> +</p> +<p> + <canvas id="my-canvas" width="300" height="20"> + </canvas> +</p></pre> + +<p>Et un peu de JavaScript:</p> + +<pre class="brush: js"> window.onload = function(){ + + var myAudio = document.getElementById('my-audio'); + var myCanvas = document.getElementById('my-canvas'); + var context = myCanvas.getContext('2d'); + + context.fillStyle = 'lightgray'; + context.fillRect(0, 0, myCanvas.width, myCanvas.height); + context.fillStyle = 'red'; + context.strokeStyle = 'white'; + + var inc = myCanvas.width / myAudio.duration; + + // afficher TimeRanges + + myAudio.addEventListener('seeked', function() { + for (i = 0; i < myAudio.buffered.length; i++) { + + var startX = myAudio.buffered.start(i) * inc; + var endX = myAudio.buffered.end(i) * inc; + var width = endX - startX; + + context.fillRect(startX, 0, width, myCanvas.height); + context.rect(startX, 0, width, myCanvas.height); + context.stroke(); + } + }); + }</pre> + +<p>Cela fonctionne mieux avec les morceaux audio ou vidéo un peu plus longs, mais appuyez sur play et cliquez sur la barre de progression du lecteur et vous devriez obtenir quelque chose comme ci-dessous. Chaque rectangle rouge remplissant le rectangle blanc représente une plage de temps.</p> + +<p><img alt="A simple audio player with play button, seek bar and volume control, with a series of red rectangles beneath it representing time ranges." src="https://mdn.mozillademos.org/files/7347/bufferedtimeranges.png" style="display: block; height: 89px; margin: 0px auto; width: 318px;"></p> + +<div class="note"> +<p><strong>Note</strong>: Vous pouvez voir <a href="http://jsbin.com/memazaro/1/edit">cet exemple en direct sur JS Bin</a>.</p> +</div> + +<h2 id="Seekable">Seekable</h2> + +<p>L'attribut <code>seekable</code> retourne un objet {{ domxref("TimeRanges") }} qui indique quelles parties du média peuvent être jouées sans chargement préalable. C'est indépendant du fait que la partie ait été téléchargée ou non: certaines parties peuvent être <em>seekable</em> mais non <em>buffered</em> si les requêtes de plage d'octets (byte-range requests) sont activées sur le serveur. Les requêtes de plage d'octets permettent aux parties du fichier média d'être délivrées du serveur et jouées presque immédiatement — et sont donc <em>seekable</em>.</p> + +<pre class="brush: js">var seekableTimeRanges = myAudio.seekable;</pre> + +<h2 id="Créer_notre_propre_barre_de_progrès">Créer notre propre barre de progrès</h2> + +<p>Si on voulait créer notre propre lecteur média, on pourrait vouloir afficher les parties du média prêtes à être jouées. Un bon moyen d'y arriver est d'utiliser l'attribut <code>seekable</code>.</p> + +<p>Bien qu'on ait vu que les parties ne sont pas nécessairement contigues, elles le sont généralement, et on peut utiliser une approximation de cette information pour donner à l'utilisateur une indication de la quantité de média qui peut être jouée directement. On peut trouver ce point en utilisant la ligne de code suivante:</p> + +<pre class="brush: js">var seekableEnd = myAudio.seekable.end(myAudio.seekable.length - 1);</pre> + +<div class="note"> +<p><strong>Note</strong>: <code>myAudio.seekable.end(myAudio.seekable.length - 1)</code> nous indique en fait le temps de fin de la dernière plage de temps disponible (et non toutes). En pratique, c'est suffisant, car le navigateur peut permettre ou non de requêter des plages d'octets. S'il ne le permet pas — <code>audio.seekable</code> sera l'équivalent de <code>audio.buffered</code> — on a une indication valide de la fin du média chargée. Sinon, alors cette valeur vaudra la durée du média presque instantannément.</p> +</div> + +<p>Il est peut-être préférable de donner une indication de la quantité de média effectivement téléchargée — c'est ce que les lecteurs natifs du navigateur semblent indiquer.</p> + +<p>Alors, construisons cela. Le HTML de notre lecteur ressemble à ça:</p> + +<pre class="brush: css"><audio id="my-audio" preload controls> + <source src="music.mp3" type="audio/mpeg"> +</audio> +<div class="buffered"> + <span id="buffered-amount"></span> +</div> +<div class="progress"> + <span id="progress-amount"></span> +</div> +</pre> + +<p>Nous utiliserons le CSS suivant pour styliser l'affichage de la mémoire tampon:</p> + +<pre class="brush: css">.buffered { + height: 20px; + position: relative; + background: #555; + width: 300px; +} + +#buffered-amount { + display: block; + height: 100%; + background-color: #777; + width: 0; +} + +.progress { + margin-top: -20px; + height: 20px; + position: relative; + width: 300px; +} + +#progress-amount { + display: block; + height: 100%; + background-color: #595; + width: 0; +}</pre> + +<p>Et le JavaScript suivant se charge notre fonctionnalité:</p> + +<pre class="brush: js">window.onload = function(){ + + var myAudio = document.getElementById('my-audio'); + + myAudio.addEventListener('progress', function() { + var duration = myAudio.duration; + if (duration > 0) { + for (var i = 0; i < myAudio.buffered.length; i++) { + if (myAudio.buffered.start(myAudio.buffered.length - 1 - i) < myAudio.currentTime) { + document.getElementById("buffered-amount").style.width = (myAudio.buffered.end(myAudio.buffered.length - 1 - i) / duration) * 100 + "%"; + break; + } + } + } + }); + + myAudio.addEventListener('timeupdate', function() { + var duration = myAudio.duration; + if (duration > 0) { + document.getElementById('progress-amount').style.width = ((myAudio.currentTime / duration)*100) + "%"; + } + }); +}</pre> + +<p>L'événement <code>progress</code> est déclenché au fur et à mesure que les données sont téléchargées, cela nous permet de réagir pour afficher la progression du téléchargement ou de la mise en mémoire tampon.</p> + +<p>L'événement <code>timeupdate</code> est declénché 4 fois par seconde au fur et à mesure que le média est joué et c'est là qu'on incrémente notre barre de progrès.</p> + +<p>Cela devrait vous donner des résultats similaires à ce qui suit, où la barre gris clair représente la progression de la mise en mémoire tampon et la barre verte montre la progression de la lecture:</p> + +<p><img alt="A simple audio player with play button, seek bar and volume control, with a bar below it. The bar has a red portion to show played video, and a dark gray bar to show how much has been buffered." src="https://mdn.mozillademos.org/files/7349/bufferedprogress.png" style="display: block; height: 67px; margin: 0px auto; width: 311px;"></p> + +<div class="note"> +<p><strong>Note</strong>: Voir pouvez <a href="http://jsbin.com/badimipi/1/edit">voir l'exemple en direct sur JS Bin</a>.</p> +</div> + +<h2 id="Un_petit_mot_sur_Played">Un petit mot sur Played</h2> + +<p>Il vaut la peine de mentionner la propriété <code>played</code> — elle nous indique quelles plages de temps ont été jouées dans le média. Par exemple:</p> + +<pre class="brush: js">var played = audio.played; // returns a TimeRanges object</pre> + +<p>Ce peut être utile pour récupérer les parties du média qui sont les plus écoutées ou regardées.</p> diff --git a/files/fr/web/guide/audio_and_video_delivery/index.html b/files/fr/web/guide/audio_and_video_delivery/index.html new file mode 100644 index 0000000000..277cd9546b --- /dev/null +++ b/files/fr/web/guide/audio_and_video_delivery/index.html @@ -0,0 +1,448 @@ +--- +title: Intégration Audio et Vidéo +slug: Web/Guide/Audio_and_video_delivery +tags: + - Audio + - HTML5 + - Media + - Video +translation_of: Web/Guide/Audio_and_video_delivery +--- +<div class="summary"> +<p>On peut délivrer de l'audio et vidéo sur le web de plusieurs manières, du fichier média statique au live stream (flux en direct) adaptatif. Cet article se veut être le point de départ pour explorer les différents mécanismes de diffusion de média sur le web et la compatiblité avec les navigateurs populaires.</p> +</div> + +<h2 id="Les_éléments_Audio_et_Vidéo">Les éléments Audio et Vidéo</h2> + +<p>Que l'on traite des fichiers audio pré-enregistrés ou des live streams, le mécanisme pour les rendre disponibles à travers un navigateur reste à peu près le même — via les éléments {{ htmlelement("audio")}} et {{ htmlelement("video")}}. Actuellement, pour supporter tous les navigateurs, il est nécessaire de définir deux formats — bien qu'avec l'adoption des formats MP3 et MP4 dans Firefox et Opera, cela change rapidement. Vous pouvez trouver les informations de compatibilité des navigateurs aux endroits suivants:</p> + +<ul> + <li><a href="/en-US/Apps/Build/Manipulating_media/Cross-browser_audio_basics#Audio_Codec_Support">Table de compatibilité des Codecs Audio</a></li> + <li><a href="/en-US/docs/Web/HTML/Supported_media_formats#Browser_compatibility">Table de compatibilité des Codecs Audio/Video</a></li> +</ul> + +<p>Pour délivrer du contenu audio et vidéo, le procédé général est comme suit:</p> + +<ol> + <li>Vérifier quels formats sont pris en charge par le navigateur via la détection de fonctionnalité</li> + <li>Si le navigateur ne lit pas nativement les formats fournis, utiliser un contenu de secours (comme une version Flash.)</li> + <li>Définir comment vous voulez jouer/instancier le média (par exemple un élément {{ htmlelement("video") }}, ou peut-être <code>document.createElement('video')</code>)</li> + <li>Ajouter le fichier média au lecteur.</li> +</ol> + +<h3 id="Audio_HTML">Audio HTML</h3> + +<pre class="brush: html"><audio controls preload="auto"> + <source src="audiofile.mp3" type="audio/mpeg"> + + <!-- fallback pour les navigateurs qui ne supportent pas mp3 --> + <source src="audiofile.ogg" type="audio/ogg"> + + <!-- fallback pour les navigateurs qui ne supportent pas la balise audio --> + <a href="audiofile.mp3">download audio</a> +</audio></pre> + +<p>Le code ci-dessus va créer un lecteur audio qui tente de précharger autant d'audio que possible pour une lecteur fluide.</p> + +<div class="note"> +<p><strong>Note</strong>: L'attribut <code>preload</code> peut être ignoré par certains navigateurs mobiles.</p> +</div> + +<p>Pour plus d'informations voir <a href="/en-US/Apps/Build/Manipulating_media/Cross-browser_audio_basics#HTML5_audio_in_detail">Les bases de l'Audio multi-navigateur (Audio HTML5 en détail)</a></p> + +<h3 id="Vidéo_HTML">Vidéo HTML</h3> + +<pre class="brush: html"><video controls width="640" height="480" poster="initialimage.png" autoplay muted> + <source src="videofile.mp4" type="video/mp4"> + + <!-- fallback pour les navigateurs qui ne supportent pas mp4 --> + <source src="videofile.webm" type="video/webm"> + + <!-- spécifie les fichiers de sous-titres --> + <track src="subtitles_en.vtt" kind="subtitles" srclang="en" label="English"> + <track src="subtitles_no.vtt" kind="subtitles" srclang="no" label="Norwegian"> + + <!-- fallback pour les navigateurs qui ne supportent pas la balise video --> + <a href="videofile.mp4">download video</a> +</video></pre> + +<p>Le code ci-dessus crée un lecteur vidéo de dimensions 640x480 pixels, affichant une image poster jusqu'à ce que la vidéo soit lue. On demande à la vidéo de passer en <code>autoplay</code> (jouer automatiquement) mais d'être <code>muted</code> (en sourdine) par défaut.</p> + +<div class="note"> +<p><strong>Note</strong>: L'attribut <code>autoplay</code> peut être ignoré par certains navigateurs mobiles.</p> +</div> + +<p>Pour plus d'informations voir {{ htmlelement("video", "l'élément vidéo") }} et <a href="/fr/Apps/Build/Manipulating_media/cross_browser_video_player">Créer un lecteur vidéo multi-navigateur</a>.</p> + +<h3 id="Contenu_de_secours_Audio_et_Vidéo">Contenu de secours Audio et Vidéo</h3> + +<p>On peut créer un contenu de secours en utilisant Flash. <a href="https://github.com/mediaelement/mediaelement/tree/master/build">Utiliser mediaelement.js</a> par exemple.</p> + +<pre class="brush: html"><audio controls> + <source src="audiofile.mp3" type="audio/mpeg"> + <source src="audiofile.ogg" type="audio/ogg"> + <!-- fallback pour les navigateurs qui ne supportent pas le tag audio --> + <a href="audiofile.mp3">download audio</a> + <object width="320" height="30" type="application/x-shockwave-flash" data="mediaelement-flash-audio.swf"> + <param name="movie" value="mediaelement-flash-audio.swf" /> + <param name="flashvars" value="controls=true&file=audiofile.mp3" /> + </object> +</audio></pre> + +<p>Le procédé est très similaire avec {{ htmlelement("video") }} — il faut juste changer le SWF utilisé.<br> + <br> + <a href="/en-US/Apps/Build/Manipulating_media/Cross-browser_audio_basics#Fallbacks">Plus d'option de Fallbacks</a>.</p> + +<h3 id="Audio_JavaScript">Audio JavaScript</h3> + +<pre class="brush: js">var myAudio = document.createElement('audio'); + +if (myAudio.canPlayType('audio/mpeg')) { + myAudio.setAttribute('src','audiofile.mp3'); +} else if (myAudio.canPlayType('audio/ogg')) { + myAudio.setAttribute('src','audiofile.ogg'); +} + +myAudio.currentTime = 5; +myAudio.play();</pre> + +<p>On définit la source de l'audio en fonction du type de fichier audio pris en charge par le navigateur, puis on place la tête de lecture à 5 secondes et essayons de lire le fichier.</p> + +<div class="note"> +<p><strong>Note</strong>: <code>Play()</code> sera ignoré par certains navigateurs mobiles à moins que l'événement ne soit initié par une action utilisateur.</p> +</div> + +<p>Il est également possible de donner un fichier WAV encodé en base64 à l'élément {{ htmlelement("audio") }}, permettant ainsi de générer de l'audio à la volée:</p> + +<pre class="brush: html"><audio id="player" src="data:audio/x-wav;base64,UklGRvC..."></audio></pre> + +<p><a href="https://github.com/kripken/speak.js/">Speak.js</a> emploie cette technique. <a href="http://speak-demo.herokuapp.com">Essayez la démo</a>.</p> + +<h3 id="Vidéo_JavaScript">Vidéo JavaScript</h3> + +<pre class="brush: js">var myVideo = document.createElement('video'); + +if (myVideo.canPlayType('video/mp4')) { + myVideo.setAttribute('src','videofile.mp4'); +} else if (myVideo.canPlayType('video/webm')) { + myVideo.setAttribute('src','videofile.webm'); +} + +myVideo.width = 480; +myVideo.height = 320;</pre> + +<p>On définit la source de la vidéo en fonction du type de fichier vidéo pris en charge par le navigateur, puis on définit la largeur et la hauteur de la vidéo.</p> + +<h2 id="API_Web_Audio">API Web Audio</h2> + +<pre class="brush: js"> var context; + var request; + var source; + + try { + context = new (window.AudioContext || window.webkitAudioContext)(); + request = new XMLHttpRequest(); + request.open("GET","http://jplayer.org/audio/mp3/RioMez-01-Sleep_together.mp3",true); + request.responseType = "arraybuffer"; + + request.onload = function() { + context.decodeAudioData(request.response, function(buffer) { + source = context.createBufferSource(); + source.buffer = buffer; + source.connect(context.destination); + // auto play + source.start(0); // start was previously noteOn + }); + }; + + request.send(); + + } catch(e) { + alert('web audio api not supported'); + }</pre> + +<p>Dans cet exemple, on récupère un fichier MP3 via XHR, on le charge et on le lit (<a href="http://jsbin.com/facutone/1/edit?js">Essayez par vous-même</a>). Pour en savoir plus sur l'API Web Audio voir <a href="/fr/docs/Web/API/Web_Audio_API/Using_Web_Audio_API">Utiliser l'API Web Audio</a>.</p> + +<h2 id="getUserMedia_Stream_API">getUserMedia / Stream API</h2> + +<p>Il est également possible de récupérer un live stream de la webcam et/ou du microphone de l'utilisateur avec <code>getUserMedia</code> et l'API Stream. Cela fait partie d'une technologie plus large connue sous le nom de WebRTC (Web Real-Time Communications) et est compatible avec les dernières versions de Chrome, Firefox et Opera.</p> + +<p>Pour récupérer un flux de la webcam, commencez par créer un élément {{htmlelement("video")}}:</p> + +<pre class="brush: html"><video id="webcam" width="480" height="360"></video></pre> + +<p>Ensuite, si cette opération est prise en charge, connectez la webcam à l'élément video:</p> + +<pre class="brush: js">navigator.getUserMedia || + (navigator.getUserMedia = navigator.mozGetUserMedia || + navigator.webkitGetUserMedia || navigator.msGetUserMedia); + +window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL; + +if (navigator.getUserMedia) { + navigator.getUserMedia({ + video: true, + audio: false + }, onSuccess, onError); +} else { + alert('getUserMedia is not supported in this browser.'); +} + +function onSuccess(stream) { + var video = document.getElementById('webcam'); + video.autoplay = true; + video.src = window.URL.createObjectURL(stream); +} + +function onError() { + alert('There has been a problem retreiving the streams - are you running on file:/// or did you disallow access?'); +}</pre> + +<p>Pour en savoir plus, lisez la page <a href="/fr/docs/NavigatorUserMedia.getUserMedia">Navigator.getUserMedia</a>.</p> + +<h2 id="Mediastream_Recording">Mediastream Recording</h2> + +<p>De nouveaux standards sont en cours de déploiement pour permettre au navigateur de récupérer le flux du micro ou de la webcam — en utilisant <code>getUserMedia</code> — et l'enregistrer directement avec la nouvelle API MediaRecorder. Pour ce faire, on prend le stream retourné par <code>getUserMedia</code>, on le donne en paramètre à un objet <code>MediaRecorder</code>, puis on utilise le résultat obtenu comme source audio ou video.<br> + <br> + Le principe de base est décrit ci-dessus:</p> + +<pre class="brush: js">var onSuccess = function(stream) { + + var mediaRecorder = new MediaRecorder(stream); + + mediaRecorder.ondataavailable = function(e) { + var audio = document.createElement('audio'); + audio.src = window.URL.createObjectURL(e.data); + } +} + +navigator.getUserMedia({audio:true}, onSuccess);</pre> + +<p>Voir <a href="/fr/docs/Web/API/MediaRecorder_API">MediaRecorder API</a> pour plus de détails.</p> + +<div class="note"> +<p><strong>Note</strong>: MediaRecorder est actuellement uniquement supporté par Firefox et uniquement pour l'audio, mais il existe des solutions pour contourner ce problème, comme la bibliothèque <a href="https://github.com/muaz-khan/WebRTC-Experiment/tree/master/RecordRTC">RecordRTC</a>.</p> +</div> + +<h2 id="Extensions_de_Source_Media">Extensions de Source Media</h2> + +<p><a href="https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html">Media Source Extensions</a> (MSE) est un brouillon de travail de W3C qui prévoit d'étendre {{domxref("HTMLMediaElement")}} pour permettre à JavaScript de générer des flux média pour la lecture. Permettre à JavaScript de générer des streams facilite toute une variété de cas d'utilisations comme le straming adaptatif et le décalage temporel des live streams.</p> + +<h3 id="Extensions_Media_Encrypté_(EME)">Extensions Media Encrypté (EME)</h3> + +<p><a href="https://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html">Encrypted Media Extensions</a> est une proposition de W3C d'étendre {{domxref("HTMLMediaElement")}} en fournissant des APIs pour contrôler la lecture de contenu protégé.<br> + <br> + L'API supporte divers cas d'utiilisation, allant de la simple décryption par clé aux vidéos protégées par DRM (pourvu que le navigateur implémente ce système). L'échange de licence/clé est contrôlé par l'application, facilitant ainsi le développement d'applications de lecture robustes et qui supportent tout une gamme de technologies de décryptage et de protection de contenu.<br> + <br> + Un des principal usage d'EME est de permettre au navigateur d'implémenter le gestion des DRM (<a href="https://fr.wikipedia.org/wiki/Gestion_des_droits_num%C3%A9riques">Digital Rights Management</a>), rendant inutiles les modules extérieurs de type Flash ou Silverlight.</p> + +<div class="note"> +<p><strong>Note</strong>: Un DRM est un système permettant de restreindre l'accès à une ressource (particulièrement les vidéos), ce qui aide à en empêcher la copie.</p> +</div> + +<h3 id="Streaming_adaptatif">Streaming adaptatif</h3> + +<p>De nouveaux formats et protocoles ont été (et sont encore) deployés pour faciliter le streaming adaptatif. Un <em>streaming adaptatif</em> est un flux en direct qui s'adapte à la bande passante disponible de l'utilisateur, typiquement, la qualité du stream peut changer en temps réel pour utiliser plus ou moins de bande passante. Le streaming adaptatif est souvent utilisé en conjonction avec le live streaming, où une diffusion fluide de l'audio et vidéo est primordiale.</p> + +<p>Les principaux encodages utilisés pour le streaming adaptatif sont <a href="/fr/Apps/Build/Audio_and_video_delivery/Live_streaming_web_audio_and_video#HLS">HLS</a> et <a href="/fr/Apps/Build/Audio_and_video_delivery/Live_streaming_web_audio_and_video#MPEG-DASH">MPEG-DASH</a>. MSE a été conçu avec DASH en tête, il définit les flux d'octets selon <a href="https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/isobmff-byte-stream-format.html">ISOBMFF</a> et <a href="http://en.wikipedia.org/wiki/M2ts">M2TS</a> (deux formats supportés par DASH, et le dernier par HLS aussi). Si vous êtes interessé par les différents standards, de manière générale, que vous cherchiez une certaine flexibilité ou souhaitiez supporter la plupart des navigateurs modernes, DASH est probablement la meilleure solution.</p> + +<div class="note"> +<p><strong>Note</strong>: Actuellement, Safari ne prend pas en charge DASH, cependant dash.js marche sur les nouvelles versions de Safari prévues pour être publiées avec OSX Yosemite.</p> +</div> + +<p>DASH fournit également un certain nombre de profils, y compris des profils <em>à la demande</em> simples, sans pré-traitement ni splitting des fichiers multimédia. Il existe un certain nombre de services en ligne qui vous permettront de convertir vos média en HLS ou DASH.<br> + <br> + Pour plus d'informations, voir <a href="/fr/Apps/Build/Audio_and_video_delivery/Live_streaming_web_audio_and_video">Live streaming web Audio et Vidéo</a>.</p> + +<h2 id="Débugger_les_problèmes_Audio_Vidéo">Débugger les problèmes Audio / Vidéo</h2> + +<p>Vous avez des problèmes de lecture audio ou vidéo? Essayez la checklist suivante.</p> + +<h3 id="Est-ce_que_le_navigateur_prend_en_charge_les_formats_fournis">Est-ce que le navigateur prend en charge les formats fournis?</h3> + +<p>Utilisez les fichiers suivants pour vérifier le support de votre format:</p> + +<ul> + <li>Audio MP3 (<code>type="audio/mpeg"</code>):<a href="http://jPlayer.org/audio/mp3/Miaow-01-Tempered-song.mp3"> http://jPlayer.org/audio/mp3/Miaow-01-Tempered-song.mp3</a> (<a href="http://jsbin.com/gekatoge/1/edit">audio MP3 en direct</a>.)</li> + <li>Audio MP4 (<code>type="audio/mp4"</code>):<a href="http://jPlayer.org/audio/m4a/Miaow-01-Tempered-song.m4a"> http://jPlayer.org/audio/m4a/Miaow-01-Tempered-song.m4a</a> (<a href="http://jsbin.com/gekatoge/2/edit">audio MP4 en direct</a>.)</li> + <li>Audio Ogg (<code>type="audio/ogg"</code>):<a href="http://jPlayer.org/audio/ogg/Miaow-01-Tempered-song.ogg"> http://jPlayer.org/audio/ogg/Miaow-01-Tempered-song.ogg</a> (<a href="http://jsbin.com/gekatoge/4/edit">audio OGG en direct</a>.)</li> + <li>Video MP4 (<code>type="video/mp4"</code>):<a href="http://jPlayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v"> http://jPlayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v</a> (<a href="http://jsbin.com/gekatoge/5/edit">vidéo MP4 en direct</a>.)</li> + <li>Video WebM (<code>type="video/webm"</code>):<a href="http://jPlayer.org/video/webm/Big_Buck_Bunny_Trailer.webm"> http://jPlayer.org/video/webm/Big_Buck_Bunny_Trailer.webm</a> (<a href="http://jsbin.com/gekatoge/6/edit">vidéo WebM en direct</a>.)</li> + <li>Video Ogg (<code>type="video/ogg"</code>):<a href="http://jPlayer.org/video/ogv/Big_Buck_Bunny_Trailer.ogv"> http://jPlayer.org/video/ogv/Big_Buck_Bunny_Trailer.ogv</a> (<a href="http://jsbin.com/gekatoge/7/edit">vidéo OGG en direct</a>.)</li> +</ul> + +<p>Si un de ces fichier n'est pas lu, c'est que le navigateur que vous testez ne prend pas en charge le format correspondant. Considérez utiliser un format différent ou un contenu de secours (Flash).<br> + <br> + Si ces fichiers fonctionnent mais que votre fichier ne fonctionne pas, il y a deux problèmes possibles:</p> + +<h3 id="Le_serveur_ne_fournit_pas_le_type_MIME_correct_du_fichier">Le serveur ne fournit pas le type MIME correct du fichier</h3> + +<p>Bien que les serveurs les prennent généralement en charge, vous allez peut-être avoir besoin d'ajouter ce qui suit à votre fichier <code>.htaccess</code>:</p> + +<pre># AddType TYPE/SUBTYPE EXTENSION + +AddType audio/mpeg mp3 +AddType audio/mp4 m4a +AddType audio/ogg ogg +AddType audio/ogg oga + +AddType video/mp4 mp4 +AddType video/mp4 m4v +AddType video/ogg ogv +AddType video/webm webm +AddType video/webm webmv</pre> + +<h3 id="Votre_fichier_n'est_pas_encodé_correctement">Votre fichier n'est pas encodé correctement</h3> + +<p>Votre fichier n'a peut-être pas été encodé correctement — essayez de l'encoder en utilisant un des outils souivants, qui se sont avérés être généralement fiables:</p> + +<ul> + <li><a href="http://audacity.sourceforge.net/">Audacity</a> - Éditeur et enregistreur audio gratuit</li> + <li><a href="http://www.getmiro.com/">Miro</a> - Lecteur audio et vidéo open-source et gratuit</li> + <li><a href="http://handbrake.fr/">Handbrake</a> - Transcodeur vidéo open-source</li> + <li><a href="http://firefogg.org/">Firefogg</a> - Encodage audio et vidéo pour Firefox</li> + <li><a href="https://www.ffmpeg.org/">FFmpeg2</a> - Encodeur en ligne de commande complet</li> + <li><a href="https://libav.org/">Libav</a> - Encodeur en ligne de commande complet</li> + <li><a href="http://m.vid.ly/">Vid.ly</a> - Video player,transcoding and delivery</li> + <li><a href="https://archive.org/">Internet Archive</a> - Transcodage et stockage gratuit</li> +</ul> + +<h2 id="Customiser_votre_Lecteur_Media">Customiser votre Lecteur Media</h2> + +<p>Vous pouvez vouloir un lecteur audio ou vidéo qui ait le même aspect sur tous les navigateurs, ou simplement vouloir l'adapter à votre site. La technique générale pour y parvenir est d'omettre l'attribut <code>controls</code> afin que les contrôles par défaut du navigateur ne s'affichent pas, et de créer vos propres contrôles en HTML et CSS, avec du JavaScript pour lier vos contrôles à l'API audio/vidéo.</p> + +<p>Si vous avez besoin de quelque chose en plus, il est possible d'ajouter des fonctionnalités qui ne sont pas présentes par défaut dans les lecteurs, tels que la vitesse de lecture, le choix de la qualité ou mêmes les spectres audio. Vous pouvez également décider de rendre votre lecteur responsive — par exemple, vous pouvez enlever la barre de progrès sous certaines conditions.</p> + +<p>Vous pouvez détecter les événements de clic, de toucher et/ou de clavier pour déclencher des actions telles que lecture, pause et stop. Il est souvent souhaitable d'ajouter des raccourcis clavier pour plus de commodité et d'accessibilité pour l'utilisateur.</p> + +<p>Un exemple rapide — d'abord, configurez votre audio et vos contrôles personnalisés en HTML:</p> + +<pre class="brush: html"> <audio id="my-audio" src="http://jPlayer.org/audio/mp3/Miaow-01-Tempered-song.mp3"></audio> + <button id="my-control">play</button></pre> + +<p>Ensuite, ajoutez un peu de JavaScript pour détecter les événements afin de lire et de mettre en pause l'audio:</p> + +<pre class="brush: js">window.onload = function() { + + var myAudio = document.getElementById('my-audio'); + var myControl = document.getElementById('my-control'); + + function switchState() { + if (myAudio.paused == true) { + myAudio.play(); + myControl.innerHTML = "pause"; + } else { + myAudio.pause(); + myControl.innerHTML = "play"; + } + } + + function checkKey(e) { + if (e.keycode == 32 ) { //spacebar + switchState(); + } + } + + myControl.addEventListener('click', function() { + switchState(); + }, false); + + window.addEventListener( "keypress", checkKey, false ); +}</pre> + +<p>Vous pouvez <a href="http://jsbin.com/jujeladu/2/edit">essayer cet exemple ici</a>. Pour plus d'informations, voir <a href="https://developer.mozilla.org/en-US/Apps/Build/Manipulating_media/Cross-browser_audio_basics#Creating_your_own_custom_audio_player">Customiser votre propre lecteur audio</a>.</p> + +<h2 id="Bibliothèques_JavaScript_AudioVidéo">Bibliothèques JavaScript Audio/Vidéo</h2> + +<p>Un certain nombre de bibliothèques JavaScript audio et vidéo existent. Les plus populaires permettent de choisir un design de lecteur cohérent sur tous les navigateurs et fournissent un contenu de secours pour les navigateurs qui ne prennent pas en charge l'audio et vidéo nativement. Le contenu de secours utilise souvent les plugins Adobe Flash ou Microsoft Silverlight. D'autres fonctionnalités telles que les éléments {{htmlelement("track")}} pour les sous-titres peuvent également être fournies par les bibliothèques média.</p> + +<h3 id="Audio_uniquement">Audio uniquement</h3> + +<ul> + <li><a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager</a></li> +</ul> + +<h3 id="Vidéo_uniquement">Vidéo uniquement</h3> + +<ul> + <li><a href="https://flowplayer.org/">flowplayer</a>: Gratuit, avec un watermark du logo flowplayer. Open source (licence GPL.)</li> + <li><a href="http://www.jwplayer.com">JWPlayer</a>: Nécessite de s'inscrire pour télécharger. Édition Open Source (Liecence Creative Commons.)</li> + <li><a href="http://www.sublimevideo.net/">SublimeVideo</a>: Nécessite de s'inscrire. Configuration par formulaire avec lien vers des bibliothèques hébergées via CDN.</li> + <li><a href="http://www.videojs.com/">Video.js</a>: Gratuit et Open Source (Licence Apache 2.)</li> +</ul> + +<h3 id="Audio_et_Vidéo">Audio et Vidéo</h3> + +<ul> + <li><a href="http://jPlayer.org">jPlayer</a>: Gratuit et Open Source (Licence MIT.)</li> + <li><a href="http://mediaelementjs.com/">mediaelement.js</a>: Gratuit et Open Source (Licence MIT.)</li> +</ul> + +<h3 id="Web_Audio_API">Web Audio API</h3> + +<ul> + <li><a href="https://github.com/cwilso/AudioContext-MonkeyPatch">AudioContext monkeypatch</a>: Un polyfill pour les anciennes versions de Web Audio API; Open Source (Licence Apache 2.)</li> +</ul> + +<h2 id="Tutoriels_Basiques">Tutoriels Basiques</h2> + +<dl> + <dt><a href="/en-US/Apps/Build/Manipulating_media/cross_browser_video_player">Creating a cross-browser video player</a></dt> + <dd>A guide to creating a basic cross browser video player using the {{ htmlelement ("video") }} element.</dd> + <dt><a href="/en-US/Apps/Build/Manipulating_media/Video_player_styling_basics">Video player styling basics</a></dt> + <dd>With the cross-browser video player put in place in the previous article, this article now looks at providing some basic, reponsive styling for the player.</dd> + <dt><a href="/en-US/Apps/Build/Manipulating_media/Cross-browser_audio_basics">Cross-browser audio basics</a></dt> + <dd> + <div> + <p>This article provides a basic guide to creating an HTML5 audio player that works cross browser, with all the associated attributes, properties and events explained, and a quick guide to custom controls created using the Media API.</p> + </div> + </dd> + <dt><a href="/en-US/Apps/Build/Manipulating_media/buffering_seeking_time_ranges">Media buffering, seeking, and time ranges</a></dt> + <dd>Sometimes it's useful to know how much {{ htmlelement("audio") }} or {{ htmlelement("video") }} has downloaded or is playable without delay — a good example of this is the buffered progress bar of an audio or video player. This article discusses how to build a buffer/seek bar using <a href="/en-US/docs/Web/API/TimeRanges">TimeRanges</a>, and other features of the media API.</dd> + <dt><a href="/en-US/Apps/Build/Manipulating_media/HTML5_playbackRate_explained">HTML5 playbackRate explained</a></dt> + <dd>The <code>playbackRate</code> property allows us to change the speed or rate at which a piece of web audio or video is playing. This article explains it in detail.</dd> + <dt><a href="/en-US/docs/Web/API/Web_Audio_API/Using_Web_Audio_API">Using the Web Audio API</a></dt> + <dd>Explains the basics of using the Web Audio API to grab, manipulate and play back an audio source.</dd> +</dl> + +<h2 id="Tutoriels_Streaming_de_médias">Tutoriels Streaming de médias</h2> + +<dl> + <dt><a href="/en-US/Apps/Build/Manipulating_media/Live_streaming_web_audio_and_video">Live streaming web audio and video</a></dt> + <dd>Live streaming technology is often employed to relay live events such as sports, concerts and more generally TV and Radio programmes that are output live. Often shortened to just streaming, live streaming is the process of transmitting media 'live' to computers and devices. This is a fairly complex and nascent subject with a lot of variables, so in this article we'll introduce you to the subject and let you know how you can get started.</dd> + <dt><a href="/en-US/Apps/Build/Manipulating_media/Setting_up_adaptive_streaming_media_sources">Setting up adaptive streaming media sources</a></dt> + <dd>Let's say you want to set up an adaptive streaming media source on a server, to be consumed inside an HTML5 media element. How would you do that? This article explains how, looking at two of the most common formats: MPEG-DASH and HLS (HTTP Live Streaming.)</dd> + <dt><a href="/en-US/docs/Web/HTML/DASH_Adaptive_Streaming_for_HTML_5_Video">DASH Adaptive Streaming for HTML 5 Video</a></dt> + <dd>Details how to set up adaptive streaming using DASH and WebM.</dd> +</dl> + +<h2 id="Tutoriels_Advancés">Tutoriels Advancés</h2> + +<dl> + <dt><a href="/en-US/Apps/Build/Manipulating_media/Adding_captions_and_subtitles_to_HTML5_video">Adding captions and subtitles to HTML5 video</a></dt> + <dd>This article explains how to add captions and subtitles to HTML5 {{ htmlelement("video") }}, using <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Video_Text_Tracks_Format" title="WebVTT is a format for displaying timed text tracks (e.g. subtitles) with the <track> element. The primary purpose of WebVTT files is to add subtitles to a <video>.">Web_Video_Text_Tracks_Format</a> and the {{ htmlelement("track") }} element.</dd> + <dt><a href="/en-US/docs/Web/Apps/Developing/Manipulating_media/Web_Audio_API_cross_browser" title="/en-US/docs/Web/Apps/Developing/Manipulating_media/Web_Audio_API_cross_browser">Writing Web Audio API code that works in every browser</a></dt> + <dd>A guide to writing cross browser Web Audio API code.</dd> + <dt><a href="/en-US/Apps/Developing/Manipulating_media/H.264_support_in_Firefox">H.264 support in Firefox</a></dt> + <dd>This article explains the state of support for the H.264 video format in Firefox/Firefox OS, including code examples, tips and tricks.</dd> + <dt><a href="https://hacks.mozilla.org/2014/06/easy-audio-capture-with-the-mediarecorder-api/">Easy audio capture with the MediaRecorder API</a></dt> + <dd>Explains the basics of using the MediaRecorder API to directly record a media stream.</dd> +</dl> + +<div class="note"> +<p><strong>Note</strong>: Les versions de Firefox OS 1.3 et plus supportent le protocole <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol" title="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> pour diffuser des vidéos en streaming. Une solution de secours pour les anciennes versions serait d'utiliser <code><video></code> avec un format pris en charge par Gecko (comme WebM).</p> +</div> + +<h2 id="Réferences">Réferences</h2> + +<ul> + <li><a href="/en-US/docs/Web/HTML/Element/video">The video element</a></li> + <li><a href="/en-US/docs/Web/Guide/Events/Media_events">Media events API</a></li> + <li><a href="/en-US/docs/Web/API/HTMLVideoElement">HTMLVideoElement API</a></li> + <li><a href="/en-US/docs/Web/API/MediaSource">MediaSource API</a></li> + <li><a href="/en-US/docs/Web/API/Web_Audio_API">Web Audio API</a></li> + <li><a href="/en-US/docs/Web/API/MediaRecorder_API">MediaRecorder API</a></li> + <li><a href="/en-US/docs/Web/API/Navigator.getUserMedia">getUserMedia</a></li> +</ul> + +<p> </p> diff --git a/files/fr/web/guide/audio_and_video_delivery/live_streaming_web_audio_and_video/index.html b/files/fr/web/guide/audio_and_video_delivery/live_streaming_web_audio_and_video/index.html new file mode 100644 index 0000000000..46c17d9604 --- /dev/null +++ b/files/fr/web/guide/audio_and_video_delivery/live_streaming_web_audio_and_video/index.html @@ -0,0 +1,288 @@ +--- +title: Live streaming web Audio et Vidéo +slug: Web/Guide/Audio_and_video_delivery/Live_streaming_web_audio_and_video +tags: + - Guide + - Streaming adaptatif +translation_of: Web/Guide/Audio_and_video_delivery/Live_streaming_web_audio_and_video +--- +<div class="summary"> +<p><span class="seoSummary">La technologie de <em>live streaming</em> (diffusion en direct) est souvent utilisée pour relayer des événements en direct, tels que le sport, les concerts, ou de manière plus générale les programmes TV et radio en direct. Souvent raccourci au simple terme de <em>streaming</em>, le live streaming est le processus de transmissions d'un média <em>live</em> (c'est à dire dynamique et non statique) aux ordinateurs et aux périphériques. C'est un sujet assez complexe et nouveau avec beaucoup de variables à prendre en considération, dans cet article nous allons vous introduire le sujet et vous donner des clés pour démarrer.</span></p> +</div> + +<p>La première chose à avoir en tête quand on diffuse un live stream à un navigateur est le fait que, plutôt que de jouer un fichier fini, on relaie un fichier qui est créé à la volée et qui n'a pas de début ou de fin prédéterminé.</p> + +<h2 id="Principales_différences_entre_media_en_stream_et_statique">Principales différences entre media en stream et statique</h2> + +<p>Un média statique est un média stocké dans un fichier, comme un fichier mp3 ou webm. Ce fichier se trouve sur un serveur et peut être délivré — comme la plupart des types de fichier — au navigateur. Le navigateur peut commencer à jouer le média avant de l'avoir reçu en intégralité, c'est ce qu'on appelle un <em>téléchargement progressif</em>.</p> + +<p>Un média en <em>live stream</em> n'a pas de temps de début et de fin finis comme un fichier statique, c'est un flux de données que le serveur transmet au navigateur et qui est souvent adaptatif (explication ci-dessous). Habituellement, il est nécessaire d'utiliser des formats différents et des logiciles spéciaux côté serveur pour y parvenir.</p> + +<h2 id="Streaming_adaptatif">Streaming adaptatif</h2> + +<p>Une des principale priorité du live streaming est de garder le lecteur du client synchronisé avec le flux envoyé par le serveur: le streaming adaptatif est une technique qui le permet, qui s'adapte en cas de bande passante faible. Le taux de transfert des données est contrôlé, et, s'il semble être en retard, utilise un flux qui demande moins de bande passante (et donc de qualité inférieure).</p> + +<p>Pour que ce soit possible, on doit utiliser des formats qui facilitent cette opération. Les formats de live streaming autorisent généralement une diffusion adaptative en divisant le flux en série de petits segments, et en rendant ces segments disponibles à différents qualités et débits binaires.</p> + +<h2 id="Streaming_Audio_et_Vidéo_à_la_demande">Streaming Audio et Vidéo à la demande</h2> + +<p>La technologie de streaming n'est pas utilisée exclusivement pour les live streams. Elle peut également être utilisée à la place de la méthode traditionnelle de téléchargement progressif, pour diffuser des fichiers audio et vidéo à la demande. Il y a plusieurs avantages à ça:</p> + +<ul> + <li>La latence est généralement plus faible, les médias peuvent démarrer plus rapidement</li> + <li>Le streaming adaptatif donne une meilleure expérience utilisateur sur une variété d'appareils, y compris à faible débit</li> + <li>Le média est téléchargé juste à temps, ce qui utilise la bande passante plus efficacement</li> +</ul> + +<h2 id="Protocoles_de_Streaming">Protocoles de Streaming</h2> + +<p>Tandis que les médias statiques sont généralement servis avec HTTP, il existe plusieurs protocoles pour servir un stream adaptatif; voyons les différentes options.</p> + +<h3 id="HTTP">HTTP</h3> + +<p>Pour l'instant, HTTP est de loin le protocole le plus couramment utilisé pour transférer des médias à la demande ou en stream.</p> + +<h3 id="RTMP">RTMP</h3> + +<p>Real Time Messaging Protocol (RTMP) est un protocole propriétaire développée par Macromedia (maintenant Adobe) et supporté par le plugin Adobe Flash. RTMP est disponible en plusieurs variantes, notamment RTMPE (Encrypté), RTMPS (Securisé sur SSL/TLS) et RTMPT (encapsulé dans des requêtes HTTP).</p> + +<h3 id="RTSP">RTSP</h3> + +<p>Real Time Streaming Protocol (RTSP) contrôle les sessions média entre les entités et il est souvent utilisé en combinaison avec Real-time Transport Protocol (RTP) et Real-time Control Protocol (RTCP) pour délivrer des flux média. Utiliser RTP avec RTCP permet un streaming adaptatif. Il n'est pas encore suporté nativement par la plupart des navigateurs, mais <a href="http://www.mozilla.org/en-US/firefox/os/notes/1.3/">Firefox OS 1.3 supporte RTSP</a>.</p> + +<div class="note"><strong>Note</strong>: Certains fournisseurs implémentent des protocoles de transfert propriétaires, tel que RealNetworks et leur Real Data Transport (RDT).</div> + +<h3 id="RTSP_2.0">RTSP 2.0</h3> + +<p>RTSP 2.0 est actuellement en cours de développement, il n'est pas rétro-compatible avec RTSP 1.0.</p> + +<div class="warning"> +<p><strong>Important</strong>: Bien que les balises {{ htmlelement("audio") }} et {{ htmlelement("video") }} soient agnostiques de tout protocole, aucun navigateur ne supporte actuellement autre chose que HTTP sans nécessiter de plugin, bien que cela semble être parti pour changer. De plus, les protocoles autres que HTTP peuvent être bloqués par des pare-feu et des serveurs proxy.</p> +</div> + +<h2 id="Utiliser_des_protocoles_de_streaming">Utiliser des protocoles de streaming</h2> + +<p>Le procédé pour utiliser différents protocoles vous sera familier si vous avez l'habitude de travailler avec les média sur HTTP — il suffit de spécifier le protocole.</p> + +<p>Par exemple:</p> + +<pre class="brush: html"><video src="rtsp://myhost.com/mymedia.format"> + <!-- Fallback here --> +</video></pre> + +<h2 id="Extensions_de_Sources_Média_(MSE)">Extensions de Sources Média (MSE)</h2> + +<p><a href="https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html">Media Source Extensions</a> est un brouillon de travail de W3C qui prévoit d'étendre {{ domxref("HTMLMediaElement") }} pour permettre à JavaScript de générer des flux média pour la lecture. Permettre à JavaScript de générer des streams facilite toute une variété de cas d'utilisations comme le streaming adaptatif et le décalage temporel des live streams.<br> + <br> + Par exemple, <a href="http://msopentech.com/blog/2014/01/03/streaming_video_player/">vous pourriez implémenter MPEG-DASH en utilisant JavaScript tout en laissant le décodage à la charge de MSE</a>.</p> + +<div class="note"> +<p><strong>Note</strong>: Le décalage temporel est le processus de lire un live stream quelque temps après qu'il ait été diffusé.</p> +</div> + +<h2 id="Formats_de_fichiers_Vidéo_en_Streaming">Formats de fichiers Vidéo en Streaming</h2> + +<p>Quelques formats de vidéo en live streaming HTTP commençent à être pris en charge parmi les navigateurs.</p> + +<div class="note"> +<p><strong>Note</strong>: Vous pouvez trouver un guide pour encoder HLS et MPEG-DASH pour une utilisation sur le web sur <a href="/fr/Apps/Build/Manipulating_media/Setting_up_adaptive_streaming_media_sources">Configuration de sources multimédia en streaming adaptatif</a>.</p> +</div> + +<h3 id="MPEG-DASH">MPEG-DASH</h3> + +<p>DASH est l'acronyme de Dynamic Adaptive Streaming over HTTP, c'est un nouveau format dont le support a récemment été ajouté à Chrome, et Internet Explorer 11 sous Windows 8.1. Il est supporté via les Extensions de Sources Media, qui sont utilisées par les bibliothèques JavaScript comme <a href="https://github.com/Dash-Industry-Forum/dash.js/">DASH.js</a>.</p> + +<p>Cette approche permet de télécharger des segments de flux vidéo en utilisant XHR et en "ajoutant" le segment au flux en cours de lecture par l'élément {{ htmlelement("video") }}. Ainsi, par exemple, si l'on détecte que le réseau est lent, on peut demander des segments de moins bonne qualité (plus petits) en cours de route. Cette technologie permet également d'ajouter/insérer un segment publicitaire dans le flux.</p> + +<div class="note"> +<p><strong>Note</strong>: Vous pouvez également <a href="http://wiki.webmproject.org/adaptive-streaming/webm-dash-specification">utiliser WebM avec le système de streaming adaptatif MPEG DASH</a>.</p> +</div> + +<h3 id="HLS">HLS</h3> + +<p>HLS (HTTP Live Streaming) est un protocole inventé par Apple Inc et il est pris en charge par iOS, Safari et les dernières versions du navigateur Android / Chrome. HLS est également adaptatif.<br> + <br> + HLS peut également être décodé en utilisant JavaScript, ce qui signifie que l'on peut supporter les dernières versions de Firefox, Chrome et Internet Explorer 10+. Voir ce <a href="https://github.com/dailymotion/hls.js">lecteur JavaScript HTTP Live Streaming</a>.<br> + <br> + Au début de la session de streaming, une <a href="http://en.wikipedia.org/wiki/M3U8#Extended_M3U_directives">playlist M3U étendue (m3u8)</a> est téléchargée. Elle contient les metadonnées des différents sous-fux fournis.</p> + +<h3 id="Suport_de_formats_de_fichiers_en_Streaming">Suport de formats de fichiers en Streaming</h3> + +<table> + <thead> + <tr> + <th>Navigateur</th> + <th>DASH</th> + <th>HLS</th> + <th>Opus (Audio)</th> + </tr> + </thead> + <tbody> + <tr> + <td>Firefox 32</td> + <td>✓ [1]</td> + <td>✓ [2]</td> + <td>✓ 14+</td> + </tr> + <tr> + <td>Safari 6+</td> + <td> </td> + <td>✓</td> + <td> </td> + </tr> + <tr> + <td>Chrome 24+</td> + <td>✓ [1]</td> + <td>✓</td> + <td> </td> + </tr> + <tr> + <td>Opera 20+</td> + <td>✓ [1]</td> + <td> </td> + <td> </td> + </tr> + <tr> + <td>Internet Explorer 10+</td> + <td>✓ 11</td> + <td>✓ [2]</td> + <td> </td> + </tr> + <tr> + <td>Firefox Mobile</td> + <td>✓</td> + <td>✓</td> + <td>✓</td> + </tr> + <tr> + <td>Safari iOS6+</td> + <td> </td> + <td>✓</td> + <td> </td> + </tr> + <tr> + <td>Chrome Mobile</td> + <td>✓</td> + <td>✓ [2]</td> + <td> </td> + </tr> + <tr> + <td>Opera Mobile</td> + <td>✓ [1]</td> + <td>✓</td> + <td> </td> + </tr> + <tr> + <td>Internet Explorer Mobile</td> + <td>✓ 11</td> + <td>✓ [2]</td> + <td> </td> + </tr> + <tr> + <td>Android</td> + <td>✓</td> + <td> </td> + <td> </td> + </tr> + </tbody> +</table> + +<p>[1] Via JavaScript et MSE</p> + +<p>[2] Via JavaScript et un Proxy CORS</p> + +<h3 id="Video_de_secours">Video de secours</h3> + +<p>Entre DASH et HLS, on peut couvrir une partie importante des navigateurs modernes mais il faut encore une solution de secours si on veut supporter le reste.<br> + <br> + Une approche populaire est d'utiliser Flash en solution de secours, qui prend en charge RTMP. Bien sûr, le problème est qu'il nous faut alors encoder dans trois formats de données différents.</p> + +<h2 id="Formats_de_fichiers_Audio_en_Streaming">Formats de fichiers Audio en Streaming</h2> + +<p>Il y a également quelques formats audio qui commençent à pris en charge par les navigateurs.</p> + +<h3 id="Opus">Opus</h3> + +<p>Opus est un format libre de droit et open source qui permet d'optimiser la qualité de différents débits binaires pour différents types audio. La musique et la parole peuvent être optimisées de différentes manières et Opus utilise les codecs SILK et CELT pour y parvenir.<br> + <br> + Actuellement, Opus est supporté par Firefox (bureau et mobile) ainsi que les dernières versions de Chrome bureau et Opera.</p> + +<div class="note"> +<p><strong>Note</strong>: <a href="http://tools.ietf.org/html/draft-ietf-rtcweb-audio-05">Opus est un format obligatoire</a> pour les implémentations navigateur de WebRTC.</p> +</div> + +<h3 id="MP3_AAC_Ogg_Vorbis">MP3, AAC, Ogg Vorbis</h3> + +<p>Les formats audio les plus courants peuvent être diffusés en stream en utilisant des technologies spécifiques côté serveur.</p> + +<div class="note"> +<p><strong>Note</strong>: Il est plus facile de diffuser de l'audio en stream en utilisant des formats qui n'ont pas été conçu pour car, contrairement aux vidéos, il n'y a pas de keyframes.</p> +</div> + +<h2 id="Technologies_de_Streaming_côté_serveur">Technologies de Streaming côté serveur</h2> + +<p>Pour diffuser de l'audio ou vidéo en live stream, vous devez exécuter un logiciel de streaming sur votre serveur ou utiliser un service tiers.</p> + +<h3 id="GStreamer">GStreamer</h3> + +<p><a href="http://gstreamer.freedesktop.org/">GStreamer</a> est un framework multimédia open source et multi-platforme qui permet de créer une variété de composants pour gérer les médias, y compris des composants de streaming. À travers son système de plugin, GStreamer fournit un support pour plus d'une centaine de codecs (dont MPEG-1, MPEG-2, MPEG-4, H.261, H.263, H.264, RealVideo, MP3, WMV, et FLV.)</p> + +<p>Des plugins GStreamer existent, tels que <a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-plugin-soup.html">souphttpclientsink</a> et <a href="https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good/html/gst-plugins-good-plugins-shout2send.html">shout2send</a>, pour diffuser en stream des médias sur HTTP. Vous pouvez également intégrer le framework Python Twisted ou utiliser quelque chose comme <a href="http://www.flumotion.net/features/">Flumotion</a> (logiciel de streaming open source).</p> + +<p>Pour le transfert RTMP, vous pouvez utiliser le <a href="https://github.com/arut/nginx-rtmp-module">module Nginx RTMP</a>.</p> + +<h3 id="SHOUTcast">SHOUTcast</h3> + +<p><a href="http://en.wikipedia.org/wiki/SHOUTcast">SHOUTcast</a> est une technologie propriétaire multi-plateforme pour diffuser des médias en streaming. Développé par Nullsoft, elle permet de diffuser du contenu audio au format MP3 ou AAC en broadcast. Pour utilisation sur le web, les streams SHOUTcast sont transmis sur HTTP.</p> + +<div class="note"> +<p><strong>Note</strong>: <a href="http://stackoverflow.com/questions/2743279/how-could-i-play-a-shoutcast-icecast-stream-using-html5">Les urls SHOUTcast peuvent nécessiter l'ajout d'un point-virgule à la fin</a>.</p> +</div> + +<h3 id="Icecast">Icecast</h3> + +<p>Le serveur <a href="http://www.icecast.org/">Icecast</a> est une technologie open source pour diffuser des média en streaming. Maintenu par <a href="http://www.xiph.org/">Xiph.org Foundation</a>, il diffuse les formats Ogg Vorbis/Theora ainsi que MP3 et AAC via le protocole SHOUTcast.</p> + +<div class="note"> +<p><strong>Note</strong>: SHOUTcast et Icecast font partie des technologies les plus répandues et les plus populaires, mais il existe de nombreux <a href="http://en.wikipedia.org/wiki/List_of_streaming_media_systems#Servers">autres systèmes de diffusion en streaming disponibles</a>.</p> +</div> + +<h3 id="Services_de_Streaming">Services de Streaming</h3> + +<p>Bien que vous ayez la possibilité d'installer des logiciels tels que GStreamer, SHOUTcast et Icecast, vous pouvez également trouver de nombreux <a href="http://en.wikipedia.org/wiki/Comparison_of_streaming_media_systems">services de streaming tiers</a> qui feront le travail pour vous.</p> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul class="task-list"> + <li><a href="http://en.wikipedia.org/wiki/HTTP_Live_Streaming">HTTP Live Streaming</a></li> + <li><a href="http://www.jwplayer.com/html5/hls/">HLS Browser Support</a></li> + <li><a href="https://github.com/RReverser/mpegts">HTTP Live Streaming JavaScript player</a></li> + <li><a href="http://www.larryjordan.biz/app_bin/wordpress/archives/2369">The Basics of HTTP Live Streaming</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/DASH_Adaptive_Streaming_for_HTML_5_Video">DASH Adaptive Streaming for HTML 5 Video</a></li> + <li><a href="http://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP">Dynamic Adaptive Streaming over HTTP (MPEG-DASH)</a></li> + <li><a href="http://dash-mse-test.appspot.com/media.html">MPEG-DASH Media Source Demo</a></li> + <li><a href="http://dashif.org/reference/players/javascript/1.0.0/index.html">DASH Reference Client</a></li> + <li><a href="http://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP">Dynamic Streaming over HTTP</a></li> + <li><a href="http://www.streamingmediaglobal.com/Articles/Editorial/Featured-Articles/The-State-of-MPEG-DASH-Deployment-96144.aspx">The State of MPEG-DASH Deployment</a></li> + <li><a href="http://www.bbc.co.uk/rd/blog/2014/03/media-source-extensions">Look, no plugins: Live streaming to the browser using Media Source Extensions and MPEG-DASH</a></li> + <li><a href="https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html">Media Source Extensions (W3C)</a></li> + <li><a href="http://en.wikipedia.org/wiki/Icecast">Icecast</a></li> + <li><a href="http://en.wikipedia.org/wiki/Shoutcast">SHOUTcast</a></li> + <li><a href="http://en.wikipedia.org/wiki/GStreamer">GStreamer</a></li> + <li><a href="https://coaxion.net/blog/2013/10/streaming-gstreamer-pipelines-via-http/">Streaming GStreamer Pipelines Via HTTP</a></li> + <li><a href="http://www.svesoftware.com/passkeeper/cms/article/streaming-media-using-gstreamer-web/">Streaming media using gstreamer on the web</a></li> + <li><a href="http://nginx-rtmp.blogspot.it/2013/07/gstreamer-and-raspberry-pi.html">GStreamer and Raspberry Pi</a></li> + <li><a href="http://msopentech.com/blog/2014/01/09/acceptance-media-source-extensions-w3c-candidate-recommendation-will-accelerate-adoption-dash-js/">Acceptance of Media Source Extensions as W3C Candidate Recommendation will accelerate adoption of dash.js</a></li> + <li><a href="http://en.wikipedia.org/wiki/Comparison_of_streaming_media_systems">Comparison of Streaming Media Systems</a></li> +</ul> + +<p><br> + </p> + +<p> </p> + +<p> </p> + +<p> </p> + +<p> </p> diff --git a/files/fr/web/guide/audio_and_video_manipulation/index.html b/files/fr/web/guide/audio_and_video_manipulation/index.html new file mode 100644 index 0000000000..eddaea4d45 --- /dev/null +++ b/files/fr/web/guide/audio_and_video_manipulation/index.html @@ -0,0 +1,366 @@ +--- +title: Manipulation Audio et Vidéo +slug: Web/Guide/Audio_and_video_manipulation +tags: + - Audio + - Canvas + - HTML5 + - Video + - Web Audio API + - WebGL +translation_of: Web/Guide/Audio_and_video_manipulation +--- +<div class="summary"> +<p>La beauté du web est qu'on peut combiner différentes technologies pour en créer de nouvelles. Avoir de l'audio et vidéo nativement dans le navigateur nous donne la possibilité d'utiliser ces flux de données avec d'autres technologies comme {{htmlelement("canvas")}}, <a href="/fr/docs/Web/API/WebGL_API">WebGL</a> ou <a href="/fr/docs/Web/API/Web_Audio_API">Web Audio API</a> pour modifier le média — par exemple ajouter des effets de réverbération ou de compression à l'audio, ou encore des filtres noir & blanc/sépia aux vidéos. Cet article fournit une référence pour expliquer ce que vous pouvez faire.</p> +</div> + +<h2 id="Manipulation_Vidéo">Manipulation Vidéo</h2> + +<p>La possibilité de lire les valeurs de pixels de chaque image d'une vidéo peut être très utile, cela nous permet de placer ces images dans d'autres contextes.</p> + +<h3 id="Vidéo_et_Canvas">Vidéo et Canvas</h3> + +<p>{{htmlelement("canvas")}} est un moyen de dessiner de manière scripté sur des pages web; c'est un outil très puissant et qui peut être couplé avec du contenu vidéo.</p> + +<p>La technique générale est comme suit:</p> + +<ol> + <li>Dessiner une image de l'élément {{htmlelement("video")}} sur un élément {{htmlelement("canvas")}} intermédiaire.</li> + <li>Lire les données de l'élément <code><canvas></code> et les manipuler.</li> + <li>Écrire les données manipulées dans le <code><canvas></code> que l'on veut afficher.</li> + <li>Marquer une pause et répéter.</li> +</ol> + +<p>On peut configurer notre lecteur vidéo et l'élément <code><canvas></code> comme ceci:</p> + +<pre class="brush: html"><video id="my-video" controls="true" width="480" height="270" crossorigin="anonymous"> + <source src="http://jplayer.org/video/webm/Big_Buck_Bunny_Trailer.webm" type="video/webm"> + <source src="http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v" type="video/mp4"> +</video> + +<canvas id="my-canvas" width="480" height="270"></canvas></pre> + +<p>Et les manipuler comme ceci: (en l'occurence, on affiche une version en noir et blanc de la vidéo)</p> + +<pre class="brush: js">var processor = { + timerCallback: function() { + if (this.video.paused || this.video.ended) { + return; + } + this.computeFrame(); + var self = this; + setTimeout(function () { + self.timerCallback(); + }, 16); // roughly 60 frames per second + }, + + doLoad: function() { + this.video = document.getElementById("my-video"); + this.c1 = document.getElementById("my-canvas"); + this.ctx1 = this.c1.getContext("2d"); + var self = this; + + this.video.addEventListener("play", function() { + self.width = self.video.width; + self.height = self.video.height; + self.timerCallback(); + }, false); + }, + + computeFrame: function() { + this.ctx1.drawImage(this.video, 0, 0, this.width, this.height); + var frame = this.ctx1.getImageData(0, 0, this.width, this.height); + var l = frame.data.length / 4; + + for (var i = 0; i < l; i++) { + var grey = (frame.data[i * 4 + 0] + frame.data[i * 4 + 1] + frame.data[i * 4 + 2]) / 3; + + frame.data[i * 4 + 0] = grey; + frame.data[i * 4 + 1] = grey; + frame.data[i * 4 + 2] = grey; + } + this.ctx1.putImageData(frame, 0, 0); + + return; + } +}; </pre> + +<p>Une fois que la page est chargée, on peut appeler</p> + +<pre class="brush: js">processor.doLoad()</pre> + +<p>{{EmbedLiveSample("Vidéo_et_Canvas", '100%', 550)}}</p> + +<div class="note"> +<p><strong>Note</strong>: En raison de problèmes de sécurité potentiels, si votre vidéo se trouve sur un domaine différent de votre page, vous devez activer <a href="/fr/docs/Web/HTTP/CORS">CORS (Cross Origin Resource Sharing)</a> sur le serveur qui héberge la vidéo et utiliser l'attribut <code>crossorigin</code> sur la balise vidéo.</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: L'exemple présenté est un exemple minimal de manipulation vidéo avec canvas; pour plus d'efficacité, vous pouvez envisager d'utiliser requestAnimationFrame à la place de setTimeout pour les navigateurs qui le prennent en charge.</p> +</div> + +<h3 id="Vidéo_e_WebGL">Vidéo e WebGL</h3> + +<p><a href="/en-US/docs/Web/WebGL">WebGL</a> est une API puissante qui utilise canvas pour (typiquement) afficher des scènes en trois dimensions. On peut combiner WebGL et l'élément {{htmlelement("video")}} pour créer des textures vidéo, ce qui veut dire que vous pouvez placer une vidéo dans des scènes 3D.</p> + +<p>Exemple:</p> + +<p>{{EmbedGHLiveSample('webgl-examples/tutorial/sample8/index.html', 670, 510) }}</p> + +<div class="note"> +<p><strong>Note</strong>: Vous pouvez trouver le <a href="https://github.com/mdn/webgl-examples/tree/gh-pages/tutorial/sample8">code source de cette démo sur GitHub</a> (<a href="https://mdn.github.io/webgl-examples/tutorial/sample8/">la voir en direct</a> aussi).</p> +</div> + +<h3 id="Vitesse_de_lecture">Vitesse de lecture</h3> + +<p>On peut ajuster la vitesse de lecture de l'audio et vidéo en utilisant l'attribut <code>playbackRate</code> (voir {{domxref("HTMLMediaElement")}}). Il prend pour valeur un nombre qui est le coefficient à appliquer à la vitesse de lecture: par exemple, 0.5 représente la moitié de la vitesse tandis que 2 représente le double.<br> + <br> + HTML:</p> + +<pre class="brush: html"><video id="my-video" controls src="http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v"></video></pre> + +<p>JavaScript:</p> + +<pre class="brush: js">var myVideo = document.getElementById('my-video'); +myVideo.playbackRate = 2;</pre> + +<div class="hidden"> +<h6 id="Playable_code" name="Playable_code">Playable code</h6> + +<pre class="brush: html"><video id="my-video" controls="true" width="480" height="270"> + <source src="http://jplayer.org/video/webm/Big_Buck_Bunny_Trailer.webm" type="video/webm"> + <source src="http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v" type="video/mp4"> +</video> +<div class="playable-buttons"> + <input id="edit" type="button" value="Edit" /> + <input id="reset" type="button" value="Reset" /> +</div> +<textarea id="code" class="playable-code"> +var myVideo = document.getElementById('my-video'); +myVideo.playbackRate = 2;</textarea> +</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var edit = document.getElementById('edit'); +var code = textarea.value; + +function setPlaybackRate() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + setPlaybackRate(); +}); + +edit.addEventListener('click', function() { + textarea.focus(); +}) + +textarea.addEventListener('input', setPlaybackRate); +window.addEventListener('load', setPlaybackRate); +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 425) }}</p> + +<div class="note"> +<p><strong>Note</strong>: Essayez l' <a href="http://jsbin.com/qomuvefu/2/edit">exemple playbackRate</a> en direct.</p> +</div> + +<div class="note"> +<p><strong>Note</strong> : <code>playbackRate</code> marche avec les éléments <code><audio></code> et <code><code><video></code></code>; cependant, dans les deux cas, la vitesse change mais pas la hauteur du son. Pour manipuler la hauteur du son, vous devez utliliser l'API Web Audio — voir la propriété {{domxref("AudioBufferSourceNode.playbackRate")}}.</p> +</div> + +<h2 id="Manipulation_Audio">Manipulation Audio</h2> + +<p>Laissons <code>playbackRate</code> de côté. Pour manipuler l'audio, on utilise typiquement l'<a href="/en-US/docs/Web/API/Web_Audio_API">API Web Audio</a>.</p> + +<h3 id="Sélectionner_une_source_audio">Sélectionner une source audio</h3> + +<p>On peut utiliser la piste audio d'un élément {{htmlelement("audio")}} ou {{htmlelement("video")}} comme source pour alimenter l'API Web Audio, ou un simple buffer audio, une onde sinusoïdale/oscillateur, un flux (comme <a href="/fr/docs/NavigatorUserMedia.getUserMedia">getUserMedia</a> de <a href="/fr/docs/Web/API/WebRTC_API">WebRTC</a>)... Découvrez exactement comment les utiliser en lisant les pages suivantes:</p> + +<ul> + <li>{{domxref("MediaElementAudioSourceNode")}}</li> + <li>{{domxref("AudioBufferSourceNode")}}</li> + <li>{{domxref("OscillatorNode")}}</li> + <li>{{domxref("MediaStreamAudioSourceNode")}}</li> +</ul> + +<h3 id="Filtres_Audio">Filtres Audio</h3> + +<p>L'API Web Audio a beaucoup de différents filtres/effets qui peuvent être appliqués à l'audio en utilisant {{domxref("BiquadFilterNode")}}, par exemple:</p> + +<p>HTML:</p> + +<pre class="brush: html"><video id="my-video" controls src="myvideo.mp4" type="video/mp4"></video></pre> + +<p>JavaScript:</p> + +<pre class="brush: js">var context = new AudioContext(), + audioSource = context.createMediaElementSource(document.getElementById("my-video")), + filter = context.createBiquadFilter(); +audioSource.connect(filter); +filter.connect(context.destination); + +// Configure filter +filter.type = "lowshelf"; +filter.frequency.value = 1000; +filter.gain.value = 25;</pre> + +<div class="hidden"> +<h6 id="Playable_code_2" name="Playable_code_2">Playable code</h6> + +<pre class="brush: html"><video id="my-video" controls="true" width="480" height="270" crossorigin="anonymous"> + <source src="http://jplayer.org/video/webm/Big_Buck_Bunny_Trailer.webm" type="video/webm"> + <source src="http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v" type="video/mp4"> +</video> +<div class="playable-buttons"> + <input id="edit" type="button" value="Edit" /> + <input id="reset" type="button" value="Reset" /> +</div> +<textarea id="code" class="playable-code"> +filter.type = "lowshelf"; +filter.frequency.value = 1000; +filter.gain.value = 25;</textarea></pre> + +<pre class="brush: js">var context = new AudioContext(), + audioSource = context.createMediaElementSource(document.getElementById("my-video")), + filter = context.createBiquadFilter(); +audioSource.connect(filter); +filter.connect(context.destination); + +var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var edit = document.getElementById('edit'); +var code = textarea.value; + +function setFilter() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + setFilter(); +}); + +edit.addEventListener('click', function() { + textarea.focus(); +}) + +textarea.addEventListener('input', setFilter); +window.addEventListener('load', setFilter); +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', 700, 425) }}</p> + +<div class="note"> +<p><strong>Note</strong>: À moins que <a href="/en-US/docs/Web/HTTP/Access_control_CORS">CORS</a> ne soit activé, vous devrez pour éviter les problèmes de sécurité placer la vidéo sur le même domaine que votre code.</p> +</div> + +<p>Les filtres pouvant être appliqués sont:</p> + +<ul> + <li>Low Pass: Les fréquences en dessous de la fréquence de coupure sont inchangées et celles au-dessus sont atténuées.</li> + <li>High Pass: Les fréquences au-dessus de la fréquence de coupure sont inchangées et celles en dessous sont atténuées.</li> + <li>Band Pass: Les fréquence comprises entre deux bornes sont inchangées et celles en dehors sont atténuées.</li> + <li>Low Shelf: Les fréquences basses obtiennent un boost (ou une atténuation).</li> + <li>High Shelf: Les fréquences hautes obtiennent un boost (ou une atténuation).</li> + <li>Peaking: Les fréquences à l'intérieur d'une gamme donnée obtiennent un boost (ou une atténuation).</li> + <li>Notch: Les fréquences à l'intérieur d'une gamme donnée sont atténuées.</li> + <li>Allpass: Laisse touts les fréquences inchangées mais modifie le rapport de phrase entre les différentes fréquences.</li> +</ul> + +<div class="note"> +<p><strong>Note</strong>: Voir {{domxref("BiquadFilterNode")}} pour plus d'informations.</p> +</div> + +<h3 id="Convolutions_et_Impulsions">Convolutions et Impulsions</h3> + +<p>Il est également possible d'appliquer des réponses impulsionnelles à l'audio en utilisant {{domxref("ConvolverNode")}}. Une <em>réponse impulsionnelle</em> (<em>impulse response</em> en anglais) est un son crée après une brève impulsion sonore (comme un applaudissement) et qui s'applique sur l'environnement qui l'a créée. Exemple: un écho crée en frappant des mains dans un tunnel.</p> + +<p>Exemple:</p> + +<pre class="brush: js">var convolver = context.createConvolver(); +convolver.buffer = this.impulseResponseBuffer; +// Connect the graph. +source.connect(convolver); +convolver.connect(context.destination);</pre> + +<div class="note"> +<p><strong>Note</strong>: Voir ce <a href="https://codepen.io/DonKarlssonSan/pen/doVKRE">Codepen</a> pour un exemple appliqué.</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: Voir {{domxref("ConvolverNode")}} pour plus d'informations.</p> +</div> + +<h3 id="Audio_dans_l'espace">Audio dans l'espace</h3> + +<p>On peut également positionner l'audio dans l'espace en utilisant un noeud panoramique (un <em>panner</em>). Ce noeud permet de définir un cône source ainsi que des éléments positionnels et directionnels — le tout dans un espace 3D définit par des coordonnées cartésiennes 3D. <br> + <br> + Exemple:</p> + +<pre class="brush: js">var panner = context.createPanner(); +panner.coneOuterGain = 0.2; +panner.coneOuterAngle = 120; +panner.coneInnerAngle = 0; + +panner.connect(context.destination); +source.connect(panner); +source.start(0); + +// Position the listener at the origin. +context.listener.setPosition(0, 0, 0);</pre> + +<div class="note"> +<p><strong>Note</strong>: Vous pouvez trouver un <a href="https://github.com/mdn/webaudio-examples/tree/master/panner-node">exemple sur notre repo GitHub</a> (le <a href="https://mdn.github.io/webaudio-examples/panner-node/">voir en direct</a> aussi).</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: Voir {{domxref("PannerNode")}} pour plus d'informations.</p> +</div> + +<h2 id="Codecs_JavaScript">Codecs JavaScript</h2> + +<p>Il est possible de manipuler l'audio au bas niveau en utilisant JavaScript. Cela peut être utile si vous voulez créer des codecs audio.<br> + <br> + Des bibliothèques existent actuellement pour les formats suivants:</p> + +<ul> + <li>AAC: <a href="https://github.com/audiocogs/aac.js">AAC.js</a></li> + <li>ALAC: <a href="https://github.com/audiocogs/alac.js">alac.js</a></li> + <li>FLAC: <a href="https://github.com/audiocogs/flac.js">flac.js</a></li> + <li>MP3: <a href="https://github.com/audiocogs/mp3.js">mp3.js</a></li> + <li>Opus: <a href="https://github.com/audiocogs/opus.js">Opus.js</a></li> + <li>Vorbis: <a href="https://github.com/audiocogs/vorbis.js">vorbis.js</a></li> +</ul> + +<div class="note"> +<p><strong>Note</strong>: Sur AudioCogs, vous pouvez <a href="http://audiocogs.org/codecs/">essayer quelques démos</a>; Audiocogs fournit également un Framework, <a href="http://audiocogs.org/codecs/">Aurora.js</a>, qui est destiné à vous aider à créer vos propres codecs en JavaScript.</p> +</div> + +<h2 id="Tutoriels">Tutoriels</h2> + +<ul> + <li><a href="/fr/docs/HTML/Manipulating_video_using_canvas">Manipulation vidéo avec la balise Canvas</a></li> + <li><a href="/fr/Apps/Build/Manipulating_media/HTML5_playbackRate_explained">HTML5 playbackRate expliqué</a></li> + <li><a href="/fr/docs/Web/API/Web_Audio_API/Using_Web_Audio_API">Utiliser l'API Web Audio</a></li> + <li><a href="/fr/docs/Web/API/Web_Audio_API/Web_audio_spatialization_basics">Les bases de la spatialisation audio Web</a></li> + <li><a href="/fr/docs/Web/API/WebGL_API/Tutorial/Animation_de_textures_en_WebGL#Utilisation_des_images_vid%C3%A9o_comme_texture">Utilisation des images vidéo comme texture WebGL</a> (Vous pouvez également utiliser la bilbiothèque WebGL <a href="http://threejs.org">THREE.js</a> (ou autres) pour <a href="http://stemkoski.github.io/Three.js/Video.html">obtenir cet effet</a>)</li> + <li><a href="/fr/docs/Web/API/WebGL_API/Tutorial/Animation_de_textures_en_WebGL">Animation de Textures en WebGL</a></li> + <li><a href="http://www.html5rocks.com/en/tutorials/webaudio/games/#toc-room">Developing Game Audio with the Web Audio API (Room effects and filters)</a></li> +</ul> + +<h2 id="Référence">Référence</h2> + +<ul> + <li>Les éléments {{htmlelement("audio")}} et {{htmlelement("video")}}</li> + <li>L'API {{domxref("HTMLMediaElement")}}</li> + <li>L'élément {{htmlelement("canvas")}}</li> + <li><a href="/fr/docs/Web/API/Web_Audio_API">Web Audio API</a></li> + <li><a href="/fr/docs/Web/API/AudioContext">AudioContext</a></li> + <li>Plus d'infos sur <a href="/fr/docs/Web/API/AudioContext.createPanner">PannerNode</a></li> +</ul> diff --git a/files/fr/web/guide/dom/events/creating_and_triggering_events/index.html b/files/fr/web/guide/dom/events/creating_and_triggering_events/index.html new file mode 100644 index 0000000000..686d138cfc --- /dev/null +++ b/files/fr/web/guide/dom/events/creating_and_triggering_events/index.html @@ -0,0 +1,96 @@ +--- +title: Création et déclenchement d'événements +slug: Web/Guide/DOM/Events/Creating_and_triggering_events +tags: + - API + - Avancé + - DOM + - Guide + - JavaScript + - évènements +translation_of: Web/Guide/Events/Creating_and_triggering_events +--- +<p>Cet article montre comment créer et distribuer des événements DOM. De tels événements sont généralement appelés <strong>événements synthétiques</strong> afin de les distinguer des événements levés par le navigateur lui-même.</p> + +<h2 id="Création_dévénements_personnalisés">Création d'événements personnalisés</h2> + +<p>Les événements peuvent être créés avec le constructeur <a href="https://developer.mozilla.org/fr/docs/Web/API/Event" title="/fr/docs/Web/API/Event"> <code>Event</code> </a>de cette manière :</p> + +<pre class="brush: js">var event = new Event('build'); + +//Ecouter l'événement. +elem.addEventListener('build', function (e) { ... }, false); + +//distribuer l'événement. +elem.dispatchEvent(event);</pre> + +<p>Ce constructeur est pris en charge par la plupart des navigateurs modernes (Internet Explorer étant l'exception). Pour une approche plus verbeuse (qui fonctionne avec Internet Explorer), voir <a href="#Ancienne_approche" title="#Ancienne_approche"> l'ancienne approche </a> ci-dessous.</p> + +<h3 id="Ajout_de_données_personnalisée_-_CustomEvent">Ajout de données personnalisée - CustomEvent ()</h3> + +<p>Pour ajouter d'autres données à l'objet événement, il existe l'interface CustomEvent. Dans cette interface, la propriété <code><u> <strong>detail</strong></u></code> peut être utilisée pour transmettre des données personnalisées. Par exemple, l'événement peut être créé de la manière suivante :</p> + +<pre class="brush: js">var event = new CustomEvent('build', { 'detail': elem.dataset.time });</pre> + +<p>Cela permet à la fonction qui capture l'événement (la fonction de rappel) d'accéder aux données supplémentaires :</p> + +<pre class="brush: js">function eventHandler(e) { + log('The time is: ' + e.detail); +} +</pre> + +<h3 id="Lancienne_approche"><a id="Ancienne_approche" name="Ancienne_approche"></a>L'ancienne approche</h3> + +<p>L'ancienne manière de créer des événements utilise des API inspirées par Java. Le code suivant en montre un exemple :</p> + +<pre class="brush: js">// Crée l'événement +var event = document.createEvent('Event'); + +// Nomme l'événement 'build'. +event.initEvent('build', true, true); + +// Écoute l'événement. +elem.addEventListener('build', function (e) { + // e.target correspond à elem +}, false); + +// target peut être n'importe quel Element ou autre EventTarget. +elem.dispatchEvent(event); + +</pre> + +<h2 id="Le_déclenchement_dévénements_intégrés">Le déclenchement d'événements intégrés</h2> + +<p>Cet exemple démontre la simulation d'un clic (programmation générant un événement de clic) sur une case à cocher en utilisant des méthodes DOM. <a href="http://developer.mozilla.org/samples/domref/dispatchEvent.html" title="http://developer.mozilla.org/samples/domref/dispatchEvent.html"> Voir l'exemple en action. </a></p> + +<pre class="brush: js">function simulateClick() { + var event = new MouseEvent('click', { + 'view': window, + 'bubbles': true, + 'cancelable': true + }); + var cb = document.getElementById('checkbox'); + var canceled = !cb.dispatchEvent(event); + if (canceled) { + //Un gestionnaire appelé preventDefault. + alert("canceled"); + } else { + //Aucun gestionnaires appelé preventDefault. + alert("not canceled"); + } +}</pre> + +<h2 id="Browser_compatibility" name="Browser_compatibility" style="line-height: 30px; font-size: 2.14285714285714rem;">Compatibilité des navigateurs</h2> + +<div class="hidden">Le tableau de compatibilité de cette page est généré à partir de données structurées. Si vous souhaitez contribuer aux données, veuillez consulter <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> et nous envoyer une <em>pull request</em>.</div> + +<p>{{Compat("api.Event.Event")}}</p> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li>{{domxref("document.createEvent()")}}</li> + <li>{{domxref("Event.initEvent()")}}</li> + <li>{{domxref("EventTarget.dispatchEvent()")}}</li> + <li>{{domxref("EventTarget.addEventListener()")}}</li> +</ul> diff --git a/files/fr/web/guide/dom/events/evenement_medias/index.html b/files/fr/web/guide/dom/events/evenement_medias/index.html new file mode 100644 index 0000000000..c34862e7db --- /dev/null +++ b/files/fr/web/guide/dom/events/evenement_medias/index.html @@ -0,0 +1,266 @@ +--- +title: Evénements des Médias +slug: Web/Guide/DOM/Events/evenement_medias +tags: + - Media +translation_of: Web/Guide/Events/Media_events +--- +<p>Plusieurs événements sont envoyés lors de la gestion des médias inclus dans un documentHTML en utilisant les balises {{ HTMLElement("audio") }} et {{ HTMLElement("video") }} ; ce document les liste et fournit des informations sur leur utilisation.</p> + +<table class="standard-table"> + <tbody> + <tr> + <th>Nom de l'événement</th> + <th>Description</th> + </tr> + <tr> + <td><code>abort</code></td> + <td>Envoyé lorsque la lecture est avortée ; par exemple, si le média est en cours de lecture et que cette lecture est recommencée depuis le début, cet événement est envoyé.</td> + </tr> + <tr> + <td><code>{{event("canplay")}}</code></td> + <td>Envoyé lorsqu'il y a assez de données disponibles pour que le média puisse être lu, sur au moins quelques trames. Cet événement correspond à la valeur <code>HAVE_ENOUGH_DATA</code> de la propriété <code>readyState</code>.</td> + </tr> + <tr> + <td><code>{{event("canplaythrough")}}</code></td> + <td>Envoyé quand l'état de disponibilité change pour <code>CAN_PLAY_THROUGH</code>, indiquant que le média peut être lu en entier sans interruption si la vitesse de téléchargement de celui-ci reste stable. Il sera également envoyé quand l'état de lecture bascule entre lecture et pause. <strong>Note</strong>: Changer manuellement la valeur <code>currentTime</code> peut éventuellement déclencher cet évenement dans firefox. Les autres navigateurs peuvent ne pas envoyer cet événement.</td> + </tr> + <tr> + <td><code>{{event("durationchange")}}</code></td> + <td>Les métadonnées sont chargées ou ont changées, indiquant un changement de la durée du média. Cet événement est envoyé lorsque, par exemple, assez de données ont été téléchargées pour connaitre cette durée.</td> + </tr> + <tr> + <td><code>{{event("emptied")}}</code></td> + <td>Les données du média ont été vidées ; par exemple, si le média a déjà été téléchargé, partiellement ou complètement, et que la méthode <a class="internal" href="/En/XPCOM_Interface_Reference/NsIDOMHTMLMediaElement" title="en/nsIDOMHTMLMediaElement"><code>load()</code></a> a été appellée pour le re-télécharger.</td> + </tr> + <tr> + <td>encrypted {{experimental_inline}}</td> + <td>L'agent utilisateur a trouvé des données d'initialisation d'acquisition de licence dans les données du média.</td> + </tr> + <tr> + <td><code>ended</code></td> + <td>Envoyé quand la lecture du média est terminée.</td> + </tr> + <tr> + <td><code>error</code></td> + <td>Envoyé quand une erreur intervient. L'attribut <code>error </code>de l'élément contient plus d'informations. Voir <a href="/en-US/docs/Web/Guide/HTML/Using_HTML5_audio_and_video#Error_handling">Error handling</a> pour plus de détails.</td> + </tr> + <tr> + <td><code>interruptbegin</code></td> + <td>Envoyé quand la lecture audio du média est interrompue sur un terminal Firefox OS, soit parce que l'application a été placée en arrière-plan, soit parce que la lecture d'un autre canal audio avec une priorité supérieure commence. Voir <a href="/en-US/docs/Web/API/AudioChannels_API/Using_the_AudioChannels_API">Using the AudioChannels API</a> pour plus de détails.</td> + </tr> + <tr> + <td><code>interruptend</code></td> + <td>Envoyé lorsque la lecture audio du média interrompue recommence sur un terminal Firefox OS — quand l'interruption se termine. Soit quand l'application revient au premier plan, soit quand la lecture d'un autre canal audio avec une priorité supérieure est terminée. Voir <a href="/en-US/docs/Web/API/AudioChannels_API/Using_the_AudioChannels_API">Using the AudioChannels API</a> pour plus de détails.</td> + </tr> + <tr> + <td><code>{{event("loadeddata")}}</code></td> + <td>La première frame du media a fini de se télécharger.</td> + </tr> + <tr> + <td><code>{{event("loadedmetadata")}}</code></td> + <td>Les métadonnées du média ont fini de se télécharger ; tous les attributs ont désormais toutes les informations utiles qu'ils peuvent contenir.</td> + </tr> + <tr> + <td><code>{{event("loadstart")}}</code></td> + <td>Envoyé lorsque le téléchargement du média commence.</td> + </tr> + <tr> + <td><code>mozaudioavailable</code></td> + <td>Envoyé lorsque qu'un tampon audio est fourni à la couche audio du lecteur pour traitement ; le tampon audio contient des échantilons sonores qui peuvent déjà être lus ou non au moment où l'évenement est reçu.</td> + </tr> + <tr> + <td><code>{{event("pause")}}</code></td> + <td>Envoyé quand la lecture du média est mise en pause.</td> + </tr> + <tr> + <td><code>{{event("play")}}</code></td> + <td>Envoyé quand la lecture du média commence après avoir été mise en pause ; c'est-à-dire quand elle reprend après un événement pause précédent.</td> + </tr> + <tr> + <td><code>{{event("playing")}}</code></td> + <td>Envoyé quand la lecture du média commence (soit pour la première fois, soit après avoir été mise en pause ou soit après avoir été terminée puis relancée).</td> + </tr> + <tr> + <td><code>{{event("progress")}}</code></td> + <td>Envoyé de manière périodique pour informer de la progression du téléchargement du média. L'information sur le volume de données actuellement téléchargées est disponible dans la propriété <code>buffered</code> de l'élément.</td> + </tr> + <tr> + <td><code>{{event("ratechange")}}</code></td> + <td>Envoyé lorsque la vitesse de lecture du média change.</td> + </tr> + <tr> + <td><code>{{event("seeked")}}</code></td> + <td>Envoyé lorsqu'une opération de déplacement dans le média est terminée.</td> + </tr> + <tr> + <td><code>{{event("seeking")}}</code></td> + <td>Envoyé lorsqu'une opération de déplacement dans le média commence.</td> + </tr> + <tr> + <td><code>{{event("stalled")}}</code></td> + <td>Envoyé lorsque l'agent utilisateur essaye de télécharger des données du média mais que celle-ci sont indisponibles.</td> + </tr> + <tr> + <td><code>{{event("suspend")}}</code></td> + <td>Envoyé lorsque le téléchargement du média est suspendu ; soit parce que ce téléchargement est fini, soit parce qu'il est mis en pause pour une autre raison.</td> + </tr> + <tr> + <td><code>{{event("timeupdate")}}</code></td> + <td>La position de la tête de lecture dans le média indiquée par l'attribut <code>currentTime</code> de l'élément a changée.</td> + </tr> + <tr> + <td><code>{{event("volumechange")}}</code></td> + <td>Envoyé lorsque le volume sonore du lecteur ou que l'attribut <code>muted</code> de l'élément changent.</td> + </tr> + <tr> + <td><code>{{event("waiting")}}</code></td> + <td>Envoyé lorsqu'une opération demandée (comme la lecture) est reportée en attendant la fin d'une autre opération (comme le déplacement du média).</td> + </tr> + </tbody> +</table> + +<p>Vous pouvez facilement écouter ces événements en utilisant du code ci-dessous :</p> + +<pre class="brush: js">var v = document.getElementsByTagName("video")[0]; +v.addEventListener("seeked", function() { v.play(); }, true); +v.currentTime = 10.0; +</pre> + +<p>Ce code récupère le premier élément vidéo dans le document et y attache un écouteur qui se déclenche quand l'évenement <code>seeked</code> est envoyé. Cet écouteur appèle la méthode <code>play()</code> de l'élément, qui démarre la lecture.</p> + +<p>Ensuite, en ligne 3, l'exemple définit la propriété <code>currentTime</code> de l'élement à 10.0, ce qui provoque une opération de déplacement de la tête de lecture à 10 secondes dans le média. Cet opération déclenche l'envoi d'un évenement <code>seeking</code> quand elle commence, puis un évenement <code>seeked</code> quand elle se termine.</p> + +<p>En d'autres termes, l'exemple lance le changement de la position de la tête de lecture à 10 secondes dans le média, et lance la lecture quand c'est fait.</p> + +<h2 id="Compatibilité_des_navigateurs">Compatibilité des navigateurs</h2> + +<p>{{ CompatibilityTable() }}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Fonctionnalité</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Support basique</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatGeckoDesktop("1.9.1") }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + <tr> + <td>encrypted</td> + <td>{{CompatChrome(42.0)}} + <p> </p> + </td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + <tr> + <td>load</td> + <td>{{ CompatUnknown() }}</td> + <td>{{CompatNo}} [1]</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + <tr> + <td>mozaudioavailable {{ non-standard_inline() }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatGeckoDesktop("2.0") }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + </tr> + <tr> + <td>suspend</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatGeckoDesktop("1.9.2") }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Fonctionnalité</th> + <th>Android</th> + <th>Android Webview</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + <th>Chrome for Android</th> + </tr> + <tr> + <td>Support basique</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + <tr> + <td>encrypted</td> + <td>{{ CompatNo }}</td> + <td>{{CompatChrome(43.0)}}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{CompatChrome(42.0)}} + <p> </p> + </td> + </tr> + <tr> + <td>load</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + <tr> + <td>mozaudioavailable {{ non-standard_inline() }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatGeckoMobile("2.0") }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + <tr> + <td>suspend</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + </tbody> +</table> +</div> + +<p>[1] Supprimé dans Gecko 1.9.2.</p> diff --git a/files/fr/web/guide/dom/events/index.html b/files/fr/web/guide/dom/events/index.html new file mode 100644 index 0000000000..475aa10cde --- /dev/null +++ b/files/fr/web/guide/dom/events/index.html @@ -0,0 +1,18 @@ +--- +title: Event developer guide +slug: Web/Guide/DOM/Events +tags: + - DOM + - Event + - Guide + - TopicStub + - events +translation_of: Web/Guide/Events +--- +<p>{{draft()}}</p> + +<p>Tout ce que vous devez savoir sur les événements sera présenté ici. Nous travaillons sur le nettoyage ici maintenant.</p> + +<h2 id="Docs">Docs</h2> + +<p>{{LandingPageListSubpages}}</p> diff --git a/files/fr/web/guide/dom/events/les_données_d_orientation_et_de_mouvement_expliquées/index.html b/files/fr/web/guide/dom/events/les_données_d_orientation_et_de_mouvement_expliquées/index.html new file mode 100644 index 0000000000..f7f7f0c204 --- /dev/null +++ b/files/fr/web/guide/dom/events/les_données_d_orientation_et_de_mouvement_expliquées/index.html @@ -0,0 +1,76 @@ +--- +title: Les données d'orientation et de mouvement expliquées +slug: Web/Guide/DOM/Events/Les_données_d_orientation_et_de_mouvement_expliquées +tags: + - Coordonnées + - Mobile + - Mouvement + - Orientation + - rotation +translation_of: Web/Guide/Events/Orientation_and_motion_data_explained +--- +<p>{{ Draft() }}</p> + +<h2 id="Résumé">Résumé</h2> + +<p>Lorsque vous utilisez des événements d'orientation et de mouvement, il est important de comprendre les valeurs que vous donne le navigateur. Cet article fournit des détails sur les systèmes de coordonnées en jeu et comment vous les utilisez.</p> + +<div class="warning"> +<p><strong>Attention :</strong> Actuellement, Firefox et Chrome ne gèrent pas ces coordonnées de la même manière. Prenez-y garde en les utilisant.</p> +</div> + +<h2 id="À_propos_des_cadres_de_coordonnées">À propos des cadres de coordonnées</h2> + +<p>Un <strong>cadre de coordonnées</strong> est un système grâce auquel l'orientation des trois axes (X, Y et Z) d'un objet est définie. Il existe deux cadres de coordonnées à prendre en compte lors de l'utilisation d'événements d'orientation et de mouvement:</p> + +<h3 id="Le_cadre_de_coordonnées_de_la_Terre">Le cadre de coordonnées de la Terre</h3> + +<p>Le cadre de coordonnées de la Terre est celui basé sur le centre de la Terre ; c'est-à-dire que les axes sont alignés sur la base de l'attraction de la gravité et de l'orientation nord magnétique standard. Nous utilisons des lettres majuscules ("X", "Y" et "Z") pour décrire les axes du cadre de coordonnées de la Terre.</p> + +<ul> + <li>L'axe <strong>X</strong> suit le plan du sol, perpendiculaire à l'axe Y, et positif vers l'est (et donc négatif vers l'ouest).</li> + <li>L'axe <strong>Y</strong> suit le plan du sol et est positif vers le vrai nord (c'est-à-dire le pôle nord, pas le nord magnétique) et négatif vers le vrai sud.</li> + <li>L'axe <strong>Z</strong> est perpendiculaire au plan du sol ; pensez-y comme une ligne tracée entre l'appareil et le centre de la Terre. La valeur de la coordonnée Z est positive vers le haut (loin du centre de la Terre) et négative vers le bas (vers le centre de la Terre).</li> +</ul> + +<h3 id="Le_cadre_de_coordonnées_de_l'appareil">Le cadre de coordonnées de l'appareil</h3> + +<p>Le cadre de coordonnées de l'appareil est basé sur le centre de l'appareil. Nous utilisons des lettres minuscules ("x", "y" et "z") pour décrire les axes du cadre de coordonnées de l'appareil.</p> + +<p><img alt="axes.png" class="default internal" src="/@api/deki/files/5694/=axes.png"></p> + +<ul> + <li>L'axe <strong>x</strong> est dans le plan de l'écran et est positif vers la droite et négatif vers la gauche.</li> + <li>L'axe <strong>y</strong> est dans le plan de l'écran et est positif vers le haut et négatif vers le bas.</li> + <li>L'axe <strong>z</strong> est perpendiculaire à l'écran ou au clavier et positif à partir de l'écran.</li> +</ul> + +<div class="note"><strong>Note :</strong> Sur un téléphone ou une tablette, l'orientation de l'appareil est toujours considérée par rapport à l'orientation standard de l'écran ; c'est l'orientation "portrait" sur la plupart des appareils. Sur un ordinateur portable, l'orientation est considérée par rapport au clavier. Si vous voulez détecter les changements d'orientation de l'appareil pour compenser, vous pouvez utiliser l'évènement <code>orientationchange</code>.</div> + +<h2 id="À_propos_de_la_rotation">À propos de la rotation</h2> + +<p>La rotation est décrite pour un axe donné en nombre de degrés d'écart entre le cadre de coordonnées de l'appareil et le cadre de coordonnées de la Terre, et est mesurée en degrés.</p> + +<h3 id="Alpha">Alpha</h3> + +<p>La rotation autour de l'axe z -- c'est-à-dire, son déplacement latéral, vers la gauche ou la droite - fait changer l'angle de rotation alpha :</p> + +<p><img alt="alpha.png" class="default internal" src="/@api/deki/files/5695/=alpha.png"></p> + +<p>L'angle alpha est de 0° quand le haut de l'appareil pointe vers le pôle nord, et augmente lorsque l'appareil est tourné vers la gauche.</p> + +<h3 id="Beta">Beta</h3> + +<p>La rotation autour de l'axe x -- c'est-à-dire, l'inclinaison de l'appareil de ou vers l'utilisateur -- provoque le changement de l'angle de rotation <strong>beta</strong> :</p> + +<p><img alt="beta.png" class="default internal" src="/@api/deki/files/5696/=beta.png"></p> + +<p>L'angle beta est de 0° lorsque le haut et le bas de l'appareil sont à la même distance de la surface de la Terre, et augmente vers 180 ° lorsque l'appareil est incliné vers l'avant et diminue vers -180 ° lorsque l'appareil est incliné vers l'arrière.</p> + +<h3 id="Gamma">Gamma</h3> + +<p>La rotation autour de l'axe Y -- c'est-à-dire, l'inclinaison de l'appareil vers la gauche ou la droite -- modifie l'angle de rotation <strong>gamma</strong> :</p> + +<p><img alt="gamma.png" class="default internal" src="/@api/deki/files/5697/=gamma.png"></p> + +<p>L'angle gamma est de 0° lorsque les côtés gauche et droit de l'appareil sont à la même distance de la surface de la Terre et augmente vers 90 ° lorsque l'appareil est incliné vers la droite, et vers -90 ° lorsque l'appareil est incliné vers la gauche.</p> diff --git a/files/fr/web/guide/dom/events/touch_events/gérer_à_la_fois_événement_tactile_et_événement_de_la_souris/index.html b/files/fr/web/guide/dom/events/touch_events/gérer_à_la_fois_événement_tactile_et_événement_de_la_souris/index.html new file mode 100644 index 0000000000..97174a4763 --- /dev/null +++ b/files/fr/web/guide/dom/events/touch_events/gérer_à_la_fois_événement_tactile_et_événement_de_la_souris/index.html @@ -0,0 +1,64 @@ +--- +title: Gérer à la fois événement tactile et événement de la souris +slug: >- + Web/Guide/DOM/Events/Touch_events/Gérer_à_la_fois_événement_tactile_et_événement_de_la_souris +translation_of: Web/API/Touch_events/Supporting_both_TouchEvent_and_MouseEvent +--- +<p>{{DefaultAPISidebar("Touch Events")}}</p> + +<p>Les interfaces {{domxref("Touch_events","touch")}} permettent aux applications de créer de meilleures expériences utilisateurs sur les appareils tactiles. Pourtant, la grande majorité du contenu web actuel est développé pour fonctionner uniquement avec la souris. En conséquence, même si un navigateur supporte le tactile, le navigateur continue à <em>émuler</em> les événements de la souris, donc le contenu qui se veut fonctionner uniquement à la souris fonctionnera toujours <em>tel quel </em>sans modification directe.</p> + +<p>Idéalement, une application tactile n'a pas besoin de supporter explicitement la souris. Mais puisque le navigateur doit émuler les événements de la souris, il peut être nécessaire de gérer certains problèmes d'interaction. Ci-dessous, vous trouverez des détails concernant l'interaction et ses répercussions pour les développeurs d'application.</p> + +<h2 id="Déclenchement_de_l'événement">Déclenchement de l'événement</h2> + +<p>La norme des événements tactiles définit quelques exigences envers les navigateurs concernant l'interaction tactile et souris (voir la section <a href="https://w3c.github.io/touch-events/#mouse-events"><em>Interaction with Mouse Events and click</em></a> pour plus de détails), noter que <em>le navigateur peut déclencher à la fois des événements tactiles et des événements de la souris en réponse à une seule et même entrée de l'utilisateur.</em> Cette section décrit les exigences pouvant affecter une application.</p> + +<p>Si le navigateur déclenche à la fois des événements tactiles et souris en réponse à une seule entrée d'un utilisateur, le navigateur <em>doit</em> déclencher un événement {{event("touchstart")}} avant tout événement de la souris. En conséquence, si une application ne veut pas que des événements de la souris soient déclenchés sur un élément {{domxref("Touch.target","target")}} spécifiquement tactile, le gestionnaire de l'événement tactile de l'élément devrait appeler {{domxref("Event.preventDefault()","preventDefault()")}} ainsi aucun événement additionnel de la souris sera envoyé.</p> + +<p>Voici un extrait de code du gestionnaire de l'événement {{event("touchmove")}} qui appelle <code>preventDefault()</code>.</p> + +<pre class="brush: js">// touchmove handler +function process_touchmove(ev) { + // Call preventDefault() to prevent any further handling + ev.preventDefault(); +} +</pre> + +<h2 id="Ordre_des_événements">Ordre des événements</h2> + +<p>Même si l'ordre spécifique des événements tactiles et souris est défini par l'implémentation, la norme indique que l'ordre suivant est <em>représentatif:</em> pour une entrée :</p> + +<ul> + <li><code>touchstart</code></li> + <li>Zero ou plus d'événements <code>touchmove</code>, suivant le mouvement de(s) doigt(s)</li> + <li><code>touchend</code></li> + <li><code>mousemove</code></li> + <li><code>mousedown</code></li> + <li><code>mouseup</code></li> + <li><code>click</code></li> +</ul> + +<p>Si l'événement {{event("touchstart")}}, {{event("touchmove")}} ou {{event("touchend")}} est annulé pendant une interaction, aucun événement de la souris ou du click sera déclenché, et la séquence des événements qui en résulte serait seulement :</p> + +<ul> + <li><code>touchstart</code></li> + <li>Zero ou plus d'événements <code>touchmove</code>, suivant le mouvement de(s) doigt(s)</li> + <li><code>touchend</code></li> +</ul> + +<h2 id="Community">Community</h2> + +<ul> + <li><a href="https://github.com/w3c/touch-events">Touch Events Community Group</a></li> + <li><a href="https://lists.w3.org/Archives/Public/public-touchevents/">Mail list</a></li> + <li><a href="irc://irc.w3.org:6667/">W3C #touchevents IRC channel</a></li> +</ul> + +<h2 id="Related_topics_and_resources">Related topics and resources</h2> + +<ul> + <li><a href="/Web/API/Touch_events">Touch Events Overview</a></li> + <li><a href="/Web/API/Touch_events/Using_Touch_Events">Using Touch Events</a></li> + <li><a href="http://www.html5rocks.com/en/mobile/touchandmouse/">Touch and Mouse (Together Again for the First Time)</a></li> +</ul> diff --git a/files/fr/web/guide/dom/events/touch_events/index.html b/files/fr/web/guide/dom/events/touch_events/index.html new file mode 100644 index 0000000000..7f3cbae7b5 --- /dev/null +++ b/files/fr/web/guide/dom/events/touch_events/index.html @@ -0,0 +1,245 @@ +--- +title: Événements tactiles / Touch events +slug: Web/Guide/DOM/Events/Touch_events +tags: + - Tactile + - touch +translation_of: Web/API/Touch_events +--- +<p>{{DefaultAPISidebar("Touch Events")}}</p> + +<p>Afin de fournir un support de qualité pour les interfaces tactiles, les événements tactiles (<em>touch events</em>) permettent d'interpréter les interactions tactiles (sur les écrans ou trackpads).</p> + +<h2 id="Définitions">Définitions</h2> + +<dl> + <dt>Surface</dt> + <dd>La surface tactile. Cela peut être un écran ou un trackpad.</dd> +</dl> + +<dl> + <dt><strong style="font-weight: bold;">Point de toucher (<em>Touch point</em>)</strong></dt> + <dd>Le point de contact avec la surface. Cela peut être un doigt ou un stylet (ou un coude, une oreille, un nez... enfin il y a quand même des chances que cela soit un doigt).</dd> +</dl> + +<h2 id="Interfaces">Interfaces</h2> + +<dl> + <dt>{{ domxref("TouchEvent") }}</dt> + <dd>Représente l'événement qui se produit quand l'action de toucher change.</dd> + <dt>{{ domxref("Touch") }}</dt> + <dd>Représente un point unique de contact entre l'utilisateur et la surface tactile.</dd> + <dt>{{ domxref("TouchList") }}</dt> + <dd>Représente un groupe de plusieurs interactions tactiles. Cela peut par exemple être le cas quand l'utilisateur utilise plusieurs doigts pour toucher simultanément la même surface.</dd> + <dt>{{ domxref("DocumentTouch") }}</dt> + <dd>Contient des méthodes permettant de créer les objets {{ domxref("Touch") }} et {{ domxref("TouchList") }}.</dd> +</dl> + +<h2 id="Exemple">Exemple</h2> + +<p>Cet exemple permet de gérer un toucher multiple (plusieurs contacts simultanés), permettant ainsi à l'utilisateur de dessiner dans un {{ HTMLElement("canvas") }} avec plusieurs doigts. Cela ne fonctionne qu'avec les navigateurs supportant les interactions tactiles.</p> + +<div class="note"><strong>Note :</strong> Le texte qui suit utilisera le terme de « doigt » pour désigner le point de toucher entre l'utilisateur et la surface. Bien entendu, cela est transposable avec une autre méthode de toucher (stylet...).</div> + +<h3 id="Initialiser_les_gestionnaires_d'événements">Initialiser les gestionnaires d'événements</h3> + +<p>Quand la page charge, la fonction <code>startup()</code> décrite ci-dessous est appelée par l'attribut <code>onload</code> de l'élément {{ HTMLElement("body") }}.</p> + +<pre class="brush: js">function startup() { + var el = document.getElementsByTagName("canvas")[0]; + el.addEventListener("touchstart", handleStart, false); + el.addEventListener("touchend", handleEnd, false); + el.addEventListener("touchcancel", handleCancel, false); + el.addEventListener("touchleave", handleLeave, false); + el.addEventListener("touchmove", handleMove, false); +} +</pre> + +<p>Cela permet simplement d'initialiser les observateurs d'événements pour l'élément {{ HTMLElement("canvas") }} afin de pouvoir gérer ceux-ci lorsqu'ils se produisent.</p> + +<h3 id="Gérer_les_nouveaux_touchers">Gérer les nouveaux touchers</h3> + +<p>Quand un événement <code>touchstart</code> se produit, cela indique qu'un nouveau toucher s'est produit. La fonction <code>handleStart()</code> est alors appelée.</p> + +<pre class="brush: js">function handleStart(evt) { + evt.preventDefault(); + var el = document.getElementsByTagName("canvas")[0]; + var ctx = el.getContext("2d"); + var touches = evt.changedTouches; + + for (var i=0; i<touches.length; i++) { + ongoingTouches.push(touches[i]); + var color = colorForTouch(touches[i]); + ctx.fillStyle = color; + ctx.fillRect(touches[i].pageX-2, touches[i].pageY-2, 4, 4); + } +} +</pre> + +<p>Cette fonction appelle {{ domxref("event.preventDefault()") }}, ce qui évite au navigateur de continuer à traiter cet événement (le début du toucher). Cela permet aussi de ne pas déclencher d'événement de souris. On obtient ensuite le contexte, duquel on peut obtenir une liste des changements des points de toucher grâce à la propriété {{ domxref("TouchEvent.changedTouches") }} de l'événement.</p> + +<p>Après quoi, on fait une boucle sur les différents objets {{ domxref("Touch") }} de la liste. puis on les stocke dans un tableau pour ensuite dessiner les points (on souhaite peindre une ligne large de 4 pixels, on dessinera donc des points comme des carrés mesurant 4x4 pixels).</p> + +<h3 id="Dessiner_avec_les_déplacements">Dessiner avec les déplacements</h3> + +<p>Chaque fois que le(s) doigt(s) bouge(nt), un événement <code>touchmove</code> est déclenché, ce qui provoque l'appel de la fonction <code>handleMove()</code> que l'on a créée. Son rôle, dans cet exemple, est d'actualiser les informations mises en cache sur les informations tactiles et de dessiner une ligne entre la position précédente et la position actuelle pour chacune des touches.</p> + +<pre class="brush: js">function handleMove(evt) { + evt.preventDefault(); + var el = document.getElementsByTagName("canvas")[0]; + var ctx = el.getContext("2d"); + var touches = evt.changedTouches; + + ctx.lineWidth = 4; + + for (var i=0; i<touches.length; i++) { + var color = colorForTouch(touches[i]); + var idx = ongoingTouchIndexById(touches[i].identifier); + + ctx.fillStyle = color; + ctx.beginPath(); + ctx.moveTo(ongoingTouches[idx].pageX, ongoingTouches[idx].pageY); + ctx.lineTo(touches[i].pageX, touches[i].pageY); + ctx.closePath(); + ctx.stroke(); + ongoingTouches.splice(idx, 1, touches[i]); // mettre à jour la liste des touchers + } +} +</pre> + +<p>Cette fonction boucle également sur les changements de touchers. Elle consulte toutefois les informations en cache dans le tableau pour déterminer le point de départ de chaque nouveau segment. Cela se fait en consultant la propriété {{ domxref("Touch.identifier") }}. Cette propriété est un entier unique pour chaque touche, cet entier reste le même pour chaque événement tant que le doigt est en contact avec la surface.</p> + +<p>Cela permet d'obtenir les précédentes coordonnées pour chaque toucher et ainsi d'utiliser la méthode adaptée pour dessiner le segment reliant les deux positions.</p> + +<p>Une fois le segment dessiné, on appelle <a href="/fr/JavaScript/Reference/Global_Objects/Array/splice" title="en/JavaScript/Reference/Global Objects/Array/splice"><code>Array.splice()</code></a> pour remplacer les informations précédentes sur les points de toucher par les informations courantes contenues dans le tableau <code>ongoingTouches</code>.</p> + +<h3 id="Gérer_la_fin_d'un_toucher">Gérer la fin d'un toucher</h3> + +<p>Lorsqu'un utilisateur enlève son doigt de la surface, un événement <code>touchend</code> est envoyé. De la même manière, un événement <code>touchleave</code> sera envoyé si le doigt sort du canvas. Ici, les deux événements sont gérés en commun avec la fonction <code>handleEnd()</code> ci-dessous. Son rôle est de dessiner le dernier segment pour chaque toucher qui s'est fini et de retirer le point de contact de la liste.</p> + +<pre class="brush: js">function handleEnd(evt) { + evt.preventDefault(); + var el = document.getElementsByTagName("canvas")[0]; + var ctx = el.getContext("2d"); + var touches = evt.changedTouches; + + ctx.lineWidth = 4; + + for (var i=0; i<touches.length; i++) { + var color = colorForTouch(touches[i]); + var idx = ongoingTouchIndexById(touches[i].identifier); + + ctx.fillStyle = color; + ctx.beginPath(); + ctx.moveTo(ongoingTouches[i].pageX, ongoingTouches[i].pageY); + ctx.lineTo(touches[i].pageX, touches[i].pageY); + ongoingTouches.splice(i, 1); // On enlève le point + } +} +</pre> + +<p>Cette fonction ressemble beaucoup à la précédente sauf qu'ici en appelant <a href="/en/JavaScript/Reference/Global_Objects/Array/splice" title="en/JavaScript/Reference/Global Objects/Array/splice"><code>Array.splice()</code></a>, on retire simplement l'ancien point sans ajouter un point mis à jour. On arrête donc de « suivre » ce point.</p> + +<h3 id="Gérer_l'annulation_d'un_toucher">Gérer l'annulation d'un toucher</h3> + +<p>Si le doigt de l'utilisateur se balade dans l'interface du navigateur ou si un toucher doit être annulé, l'événement <code>touchcancel</code> est envoyé et on appelle alors la fonction <code>handleCancel()</code>.</p> + +<pre class="brush: js">function handleCancel(evt) { + evt.preventDefault(); + var touches = evt.changedTouches; + + for (var i=0; i<touches.length; i++) { + ongoingTouches.splice(i, 1); // on retire le point + } +} +</pre> + +<p>L'idée est ici la même que pour la fin d'un toucher, on retire simplement le point de la liste. Ici on ne dessine pas le dernier segment.</p> + +<h3 id="Fonctions_auxiliaires">Fonctions auxiliaires</h3> + +<p>Cet exemple utilise deux fonctions auxiliaires qu'il est conseillé de lire rapidement afin de mieux comprendre le reste du code.</p> + +<h4 id="Sélectionner_une_couleur_pour_chaque_toucher">Sélectionner une couleur pour chaque toucher</h4> + +<p>Afin que chaque contact soit différent, on utilisera la fonction <code>colorForTouch()</code> pour choisir un couleur unique pour chacun, basée sur l'identifiant du toucher. Cet identifiant sera toujours compris entre 0 et le nombre de touchers moins 1. Imaginons que personne n'utilisera plus de 16 touchers simultanés, on peut alors directement convertir les identifiants en niveaux de gris.</p> + +<pre class="brush: js">function colorForTouch(touch) { + var id = touch.identifier; + id = id.toString(16); // creer un nombre hexadécimal + return "#" + id + id + id; +} +</pre> + +<p>Le résultat de cette fonction sera une chaîne de caractères qui pourra être utilisée par les fonctions de l'élément {{ HTMLElement("canvas") }} pour dessiner les couleurs. Ainsi avec un identifiant initial {{ domxref("Touch.identifier") }} de 10, le résultat de cette fonction sera la chaîne "#aaa".</p> + +<h4 id="Retrouver_un_toucher_en_cours">Retrouver un toucher en cours</h4> + +<p>La fonction <code>ongoingTouchIndexById()</code> analyse le tableau <code>ongoingTouches</code> pour trouver le toucher correspondant à l'identifiant donné. Elle retourne alors l'indice du toucher dans le tableau.</p> + +<pre class="brush: js">function ongoingTouchIndexById(idToFind) { + for (var i=0; i<ongoingTouches.length; i++) { + var id = ongoingTouches[i].identifier; + + if (id == idToFind) { + return i; + } + } + return -1; // toucher non trouvé +} +</pre> + +<p><a href="/samples/domref/touchevents.html">Voir l'exemple sur une page</a></p> + +<h2 id="Astuces_supplémentaires">Astuces supplémentaires</h2> + +<p>Cette section fournit quelques astuces supplémentaires pour gérer les événements tactiles au sein de votre application web.</p> + +<h3 id="Gérer_les_clics">Gérer les clics</h3> + +<p>Étant donné que l'appel de la méthode <code>preventDefault()</code> sur l'événement <code>touchstart</code> ou le premier événement <code>touchmove</code> de la série empêche la saisie d'événements en provenance de la souris, on appelle souvent <code>preventDefault()</code> sur <code>touchmove</code> plutôt que sur <code>touchstart</code>. Ainsi, les événements de la souris peuvent continuer à se déclencher et le reste du site fonctionnera de manière habituelle. Une autre méthode parfois utilisée est de déclencher des événements de souris à partir des événements tactiles. (L'exemple qui suit représente seulement une indication. La logique a été simplifiée et ce code, tel quel, aura un comportement étrange.)</p> + +<pre class="brush: js">function onTouch(evt) { + evt.preventDefault(); + if (evt.touches.length > 1 || (evt.type == "touchend" && evt.touches.length > 0)) + return; + + var newEvt = <a href="https://developer.mozilla.org/en/DOM/document.createEvent" rel="internal" title="en/DOM/document.createEvent">document.createEvent</a>("MouseEvents"); + var type = null; + var touch = null; + switch (event.type) { + case "touchstart": type = "mousedown"; touch = event.changedTouches[0]; + case "touchmove": type = "mousemove"; touch = event.changedTouches[0]; + case "touchend": type = "mouseup"; touch = event.changedTouches[0]; + } + newEvt.<strong>initMouseEvent</strong>(type, true, true, event.<code><a href="https://developer.mozilla.org/en/DOM/event.originalTarget" rel="custom">originalTarget</a>.ownerDocument.defaultView</code>, 0, + touch.screenX, touch.screenY, touch.clientX, touch.clientY, + evt.ctrlKey, evt.altKey, evt.shirtKey, evt.metaKey, 0, null); + event.<code><a href="https://developer.mozilla.org/en/DOM/event.originalTarget" rel="custom">originalTarget</a></code>.<a href="https://developer.mozilla.org/en/DOM/element.dispatchEvent" rel="internal" title="en/DOM/element.dispatchEvent">dispatchEvent</a>(newEvt); +} +</pre> + +<h3 id="Appeler_preventDefault()_uniquement_pour_un_deuxième_toucher">Appeler preventDefault() uniquement pour un deuxième toucher</h3> + +<p>Pour éviter que des événements de zoom (comme <code>pinchZoom</code>) ne se produisent sur la page, il est possible d'appeler la méthode <code>preventDefault()</code> sur le deuxième toucher de la série. Ce comportement n'est pas encore parfaitement défini dans les différentes spécifications. Différents résultats se produisent sur les différents navigateurs (ainsi iOS empêchera le zoom mais continuera à autoriser le déroulement de la page avec deux doigts, Android autorisera le zoom mais pas le déroulement, Opera et Firefox empêcheront ces deux opérations). Il est actuellement déconseillé d'être dépendant d'un de ces comportements en particulier. Il faut plutôt utiliser les méta-données concernant la vue virtuelle (<em>viewport</em>) pour éviter un zoom quelconque.</p> + +<dl> +</dl> + +<h2 id="Compatibilité_des_navigateurs">Compatibilité des navigateurs</h2> + +<p>{{Compat("api.Touch")}}</p> + +<div id="compat-mobile"> </div> + +<h3 id="Notes_relatives_à_Gecko">Notes relatives à Gecko</h3> + +<p>Le paramètre <code>dom.w3c_touch_events.enabled</code> peut être utilisé avec ses trois états pour désactiver (0), activer (1) et détecter automatiquement (2) le support des événements tactiles. La valeur par défaut est la détection automatique (2). Une fois que le paramètre a été changé, il est nécessaire de redémarrer le navigateur.</p> + +<div class="geckoVersionNote" style=""> +<p>{{ gecko_callout_heading("12.0") }}</p> + +<p>Avant Gecko 12.0 {{ geckoRelease("12.0") }}, Gecko ne supportait pas les contacts multiples simultanés. Seul un toucher à la fois était supporté.</p> +</div> + +<div class="note"><strong>Note : </strong>Avant Gecko 6.0 {{ geckoRelease("6.0") }}, Gecko permettait d'utiliser une <a href="/en/DOM/Touch_events_(Mozilla_experimental)" title="en/DOM/Touch events (Mozilla experimental)">API propriétaire pour les événements tactile.</a> Cette API est maintenant dépréciée, celle-ci doit être utilisée à la place.</div> diff --git a/files/fr/web/guide/dom/index.html b/files/fr/web/guide/dom/index.html new file mode 100644 index 0000000000..3fa42aa4d9 --- /dev/null +++ b/files/fr/web/guide/dom/index.html @@ -0,0 +1,29 @@ +--- +title: Guides DOM pour développeurs +slug: Web/Guide/DOM +tags: + - API + - DOM + - Guide + - TopicStub +translation_of: Web/API/Document_Object_Model +--- +<p>{{draft}}</p> + +<p>Le <a href="/docs/DOM">Document Object Model</a> est une API pour les documents <a href="/en-US/docs/HTML">HTML</a> et <a href="/en-US/docs/XML">XML</a>. Il fournit une représentation structurelle du document, permettant au développeur de modifier son contenu et sa présentation visuelle. Essentiellement, il connecte des pages Web à des scripts ou des langages de programmation.</p> + +<p>Toutes les propriétés, méthodes, et événements disponible pour le développeur web pour manipuler et créer des pages Web sont organisés en <a href="/en-US/docs/Gecko_DOM_Reference">objects</a> (par exemple, l'objet de document qui représente le document lui-même, l'objet de table qui représente un élément de tableau HTML, etc.). Ces objets sont accessibles via les langages de script dans les navigateurs Web les plus récents.</p> + +<p>Le DOM est le plus souvent utilisé en conjonction avec <a href="/en-US/docs/JavaScript">JavaScript</a>. Cependant, le DOM a été conçu pour être indépendant de tout langage de programmation particulier, rendant la représentation structurelle du document disponible à partir d'une API unique et cohérente. <span class="tlid-translation translation" lang="fr"><span title="">Bien que nous nous concentrions sur JavaScript tout au long de ce site, les implémentations du DOM peuvent être construites pour</span></span> <a href="http://www.w3.org/DOM/Bindings">n'importe quel langage</a>.</p> + +<p>Le <a href="http://www.w3.org/">World Wide Web Consortium</a> établit une <a href="http://www.w3.org/DOM/">norme pour le DOM</a>, appelée W3C DOM. Il devrait, maintenant que les navigateurs les plus importants l'implémentent correctement, activer de puissantes applications multi-navigateurs.</p> + +<h2 id="Why_is_the_DOM_support_in_Mozilla_important.3F" name="Why_is_the_DOM_support_in_Mozilla_important.3F">Pourquoi le DOM est-il important?</h2> + +<p>"HTML dynamique" (<a href="/en-US/docs/DHTML">DHTML</a>) est un terme utilisé par certains fournisseurs pour écrire la combinaison de HTML, de feuilles de style et de scripts permettant d'animer les documents. Le groupe de travail DOM du W3C travaille d'arrache-pied pour s'assurer que des solutions interopérables et indépendantes du langage sont convenues (voir également la <a href="http://www.w3.org/DOM/faq.html">FAQ du W3C</a>). Comme Mozilla revendique le titre de "Web Application Platform", la prise en charge du DOM est l'une des fonctionnalités les plus demandées, et nécessaire si Mozilla veut être une alternative viable aux autres navigateurs.</p> + +<p>Encore plus important est le fait que l'interface utilisateur de Mozilla (également Firefox et Thunderbird) est construite en utilisant <a href="/en-US/docs/XUL" title="/en-US/docs/XUL">XUL</a>, en utilisant le DOM pour <a href="/en-US/docs/Dynamically_modifying_XUL-based_user_interface">manipuler sa propre interface utilisateur</a>.</p> + +<h2 id="En_savoir_plus_sur_le_DOM">En savoir plus sur le DOM</h2> + +<p>{{LandingPageListSubpages}}</p> diff --git a/files/fr/web/guide/dom/manipuler_historique_du_navigateur/example/index.html b/files/fr/web/guide/dom/manipuler_historique_du_navigateur/example/index.html new file mode 100644 index 0000000000..f19782d753 --- /dev/null +++ b/files/fr/web/guide/dom/manipuler_historique_du_navigateur/example/index.html @@ -0,0 +1,392 @@ +--- +title: Exemple de navigation en Ajax +slug: Web/Guide/DOM/Manipuler_historique_du_navigateur/Example +translation_of: Web/API/History_API/Example +--- +<p>Voici un exemple de site web AJAX composé uniquement de trois pages (<em>page_un.php</em>, <em>page_deux.php</em> et <em>page_trois.php</em>). Pour tester cet exemple, merci de créer les fichiers suivants :</p> +<p><strong>page_un.php</strong>:</p> +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> + <pre class="brush: php"><?php + $page_title = "Page un"; + + $as_json = false; + if (isset($_GET["view_as"]) && $_GET["view_as"] == "json") { + $as_json = true; + ob_start(); + } else { +?> +<!doctype html> +<html> +<head> +<?php + include "include/header.php"; + echo "<title>" . $page_title . "</title>"; +?> +</head> + +<body> + +<?php include "include/before_content.php"; ?> + +<p>This paragraph is shown only when the navigation starts from <strong>first_page.php</strong>.</p> + +<div id="ajax-content"> +<?php } ?> + + <p>This is the content of <strong>first_page.php</strong>.</p> + +<?php + if ($as_json) { + echo json_encode(array("page" => $page_title, "content" => ob_get_clean())); + } else { +?> +</div> + +<p>This paragraph is shown only when the navigation starts from <strong>first_page.php</strong>.</p> + +<?php + include "include/after_content.php"; + echo "</body>\n</html>"; + } +?> +</pre> +</div> +<p><strong>page_deux.php</strong>:</p> +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> + <pre class="brush: php"><?php + $page_title = "Page deux"; + + $as_json = false; + if (isset($_GET["view_as"]) && $_GET["view_as"] == "json") { + $as_json = true; + ob_start(); + } else { +?> +<!doctype html> +<html> +<head> +<?php + include "include/header.php"; + echo "<title>" . $page_title . "</title>"; +?> +</head> + +<body> + +<?php include "include/before_content.php"; ?> + +<p>This paragraph is shown only when the navigation starts from <strong>second_page.php</strong>.</p> + +<div id="ajax-content"> +<?php } ?> + + <p>This is the content of <strong>second_page.php</strong>.</p> + +<?php + if ($as_json) { + echo json_encode(array("page" => $page_title, "content" => ob_get_clean())); + } else { +?> +</div> + +<p>This paragraph is shown only when the navigation starts from <strong>second_page.php</strong>.</p> + +<?php + include "include/after_content.php"; + echo "</body>\n</html>"; + } +?> +</pre> +</div> +<p><strong>page_trois.php</strong>:</p> +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> + <pre class="brush: php"><?php + $page_title = "Page trois"; + $page_content = "<p>Ceci est le contenu de la <strong>page_trois.php</strong>. Ce contenu est stocké dans une variable PHP.</p>"; + + if (isset($_GET["view_as"]) && $_GET["view_as"] == "json") { + echo json_encode(array("page" => $page_title, "content" => $page_content)); + } else { +?> +<!doctype html> +<html> +<head> +<?php + include "include/header.php"; + echo "<title>" . $page_title . "</title>"; +?> +</head> + +<body> + +<?php include "include/before_content.php"; ?> + +<p>This paragraph is shown only when the navigation starts from <strong>third_page.php</strong>.</p> + +<div id="ajax-content"> +<?php echo $page_content; ?> +</div> + +<p>This paragraph is shown only when the navigation starts from <strong>third_page.php</strong>.</p> + +<?php + include "include/after_content.php"; + echo "</body>\n</html>"; + } +?> +</pre> +</div> +<p><strong>css/style.css</strong>:</p> +<pre class="brush: css">#ajax-loader { + position: fixed; + display: table; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +#ajax-loader > div { + display: table-cell; + width: 100%; + height: 100%; + vertical-align: middle; + text-align: center; + background-color: #000000; + opacity: 0.65; +} +</pre> +<p><strong>include/after_content.php</strong>:</p> +<pre class="brush: php"><p>Ceci est le pied-de-page. Il est commun à toutes les pages ajax.</p> +</pre> +<p><strong>include/before_content.php</strong>:</p> +<pre class="brush: php"><p> +[ <a class="ajax-nav" href="page_un.php">Premier exemple</a> +| <a class="ajax-nav" href="page_deux.php">Second exemple</a> +| <a class="ajax-nav" href="page_trois.php">Troisième exemple</a> +| <a class="ajax-nav" href="inexistante.php">Page inexistante</a> ] +</p> + +</pre> +<p><strong>include/header.php</strong>:</p> +<pre class="brush: php"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<script type="text/javascript" src="js/ajax_nav.js"></script> +<link rel="stylesheet" href="css/style.css" /> +</pre> +<p><strong>js/ajax_nav.js</strong>:</p> +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> + <pre class="brush: js">"use strict"; + +var ajaxRequest = new (function () { + + function closeReq () { + oLoadingBox.parentNode && document.body.removeChild(oLoadingBox); + bIsLoading = false; + } + + function abortReq () { + if (!bIsLoading) { return; } + oReq.abort(); + closeReq(); + } + + function ajaxError () { + alert("Unknown error."); + } + + function ajaxLoad () { + var vMsg, nStatus = this.status; + switch (nStatus) { + case 200: + vMsg = JSON.parse(this.responseText); + document.title = oPageInfo.title = vMsg.page; + document.getElementById(sTargetId).innerHTML = vMsg.content; + if (bUpdateURL) { + history.pushState(oPageInfo, oPageInfo.title, oPageInfo.url); + bUpdateURL = false; + } + break; + default: + vMsg = nStatus + ": " + (oHTTPStatus[nStatus] || "Unknown"); + switch (Math.floor(nStatus / 100)) { + /* + case 1: + // Informational 1xx + console.log("Information code " + vMsg); + break; + case 2: + // Successful 2xx + console.log("Successful code " + vMsg); + break; + case 3: + // Redirection 3xx + console.log("Redirection code " + vMsg); + break; + */ + case 4: + /* Client Error 4xx */ + alert("Client Error #" + vMsg); + break; + case 5: + /* Server Error 5xx */ + alert("Server Error #" + vMsg); + break; + default: + /* Unknown status */ + ajaxError(); + } + } + closeReq(); + } + + function filterURL (sURL, sViewMode) { + return sURL.replace(rSearch, "") + ("?" + sURL.replace(rHost, "&").replace(rView, sViewMode ? "&" + sViewKey + "=" + sViewMode : "").slice(1)).replace(rEndQstMark, ""); + } + + function getPage (sPage) { + if (bIsLoading) { return; } + oReq = new XMLHttpRequest(); + bIsLoading = true; + oReq.onload = ajaxLoad; + oReq.onerror = ajaxError; + if (sPage) { oPageInfo.url = filterURL(sPage, null); } + oReq.open("get", filterURL(oPageInfo.url, "json"), true); + oReq.send(); + oLoadingBox.parentNode || document.body.appendChild(oLoadingBox); + } + + function requestPage (sURL) { + if (history.pushState) { + bUpdateURL = true; + getPage(sURL); + } else { + /* Ajax navigation is not supported */ + location.assign(sURL); + } + } + + function processLink () { + if (this.className === sAjaxClass) { + requestPage(this.href); + return false; + } + return true; + } + + function init () { + oPageInfo.title = document.title; + for (var oLink, nIdx = 0, nLen = document.links.length; nIdx < nLen; document.links[nIdx++].onclick = processLink); + } + + const + + /* customizable constants */ + sTargetId = "ajax-content", sViewKey = "view_as", sAjaxClass = "ajax-nav", + + /* not customizable constants */ + rSearch = /\?.*$/, rHost = /^[^\?]*\?*&*/, rView = new RegExp("&" + sViewKey + "\\=[^&]*|&*$", "i"), rEndQstMark = /\?$/, + oLoadingBox = document.createElement("div"), oCover = document.createElement("div"), oLoadingImg = new Image(), + oPageInfo = { + title: null, + url: location.href + }, oHTTPStatus = /* http://www.iana.org/assignments/http-status-codes/http-status-codes.xml */ { + 100: "Continue", + 101: "Switching Protocols", + 102: "Processing", + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Non-Authoritative Information", + 204: "No Content", + 205: "Reset Content", + 206: "Partial Content", + 207: "Multi-Status", + 208: "Already Reported", + 226: "IM Used", + 300: "Multiple Choices", + 301: "Moved Permanently", + 302: "Found", + 303: "See Other", + 304: "Not Modified", + 305: "Use Proxy", + 306: "Reserved", + 307: "Temporary Redirect", + 308: "Permanent Redirect", + 400: "Bad Request", + 401: "Unauthorized", + 402: "Payment Required", + 403: "Forbidden", + 404: "Not Found", + 405: "Method Not Allowed", + 406: "Not Acceptable", + 407: "Proxy Authentication Required", + 408: "Request Timeout", + 409: "Conflict", + 410: "Gone", + 411: "Length Required", + 412: "Precondition Failed", + 413: "Request Entity Too Large", + 414: "Request-URI Too Long", + 415: "Unsupported Media Type", + 416: "Requested Range Not Satisfiable", + 417: "Expectation Failed", + 422: "Unprocessable Entity", + 423: "Locked", + 424: "Failed Dependency", + 425: "Unassigned", + 426: "Upgrade Required", + 427: "Unassigned", + 428: "Precondition Required", + 429: "Too Many Requests", + 430: "Unassigned", + 431: "Request Header Fields Too Large", + 500: "Internal Server Error", + 501: "Not Implemented", + 502: "Bad Gateway", + 503: "Service Unavailable", + 504: "Gateway Timeout", + 505: "HTTP Version Not Supported", + 506: "Variant Also Negotiates (Experimental)", + 507: "Insufficient Storage", + 508: "Loop Detected", + 509: "Unassigned", + 510: "Not Extended", + 511: "Network Authentication Required" + }; + + var + + oReq, bIsLoading = false, bUpdateURL = false; + + oLoadingBox.id = "ajax-loader"; + oCover.onclick = abortReq; + oLoadingImg.src = "data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="; + oCover.appendChild(oLoadingImg); + oLoadingBox.appendChild(oCover); + + onpopstate = function (oEvent) { + bUpdateURL = false; + oPageInfo.title = oEvent.state.title; + oPageInfo.url = oEvent.state.url; + getPage(); + }; + + window.addEventListener ? addEventListener("load", init, false) : window.attachEvent ? attachEvent("onload", init) : (onload = init); + + // Public methods + + this.open = requestPage; + this.stop = abortReq; + this.rebuildLinks = init; + +})(); +</pre> +</div> +<div class="note" id="const_compatibility"> + <strong>Note:</strong> <a href="/en/JavaScript/Reference/Statements/const" title="en/JavaScript/Reference/Statements/const"><code>const</code></a> (instruction de constante) <strong>ne fait pas partie de ECMAScript 5</strong>. Il est supporté dans Firefox et Chrome (V8) et partiellement supporté dans Opera 9+ et Safari. <strong>Il n'est pas supporté dans Internet Explorer 6-9, ou dans la version de prévisualisation de Internet Explorer 10</strong>. <a href="/en/JavaScript/Reference/Statements/const" title="en/JavaScript/Reference/Statements/const"><code>const</code></a> sera défini par ECMAScript 6, mais avec une sémantique différente. Proches des variables déclarées avec l'instruction <a href="/en/JavaScript/Reference/Statements/let" title="en/JavaScript/Reference/Statements/let"><code>let</code></a>, les constantes déclarées avec <a href="/en/JavaScript/Reference/Statements/const" title="en/JavaScript/Reference/Statements/const"><code>const</code></a> seront limitées en portée. <strong>Nous ne l'avons utilisé que pour des raisons pédagogiques, si vous souhaitez une compatibilité maximale de ce code, merci de remplacer les références à </strong><strong><a href="/en/JavaScript/Reference/Statements/const" title="en/JavaScript/Reference/Statements/const"><code>const</code></a> par des instructions <a href="/en/JavaScript/Reference/Statements/var" title="en/JavaScript/Reference/Statements/var"><code>var</code></a>.</strong></div> +<p>Pour plus d'informations, voyez : <a href="/fr/docs/DOM/manipuler_lhistorique_du_navigateur" title="/fr/docs/DOM/manipuler_lhistorique_du_navigateur">Manipuler l'historique du navigateur</a>.</p> +<h2 id="Lire_également">Lire également</h2> +<ul> + <li>{{ domxref("window.history") }}</li> + <li>{{ domxref("window.onpopstate") }}</li> +</ul> diff --git a/files/fr/web/guide/dom/manipuler_historique_du_navigateur/index.html b/files/fr/web/guide/dom/manipuler_historique_du_navigateur/index.html new file mode 100644 index 0000000000..5e199dd521 --- /dev/null +++ b/files/fr/web/guide/dom/manipuler_historique_du_navigateur/index.html @@ -0,0 +1,245 @@ +--- +title: Manipuler l'historique du navigateur +slug: Web/Guide/DOM/Manipuler_historique_du_navigateur +tags: + - API + - DOM + - Historique +translation_of: Web/API/History_API +--- +<p>L'objet DOM {{ domxref("window") }} fournit un accès à l'historique du navigateur via l'objet {{ domxref("window.history", "history") }}. Il expose un ensemble de méthodes et de propriétés qui permettent d'avancer et de reculer dans l'historique de l'utilisateur ainsi que -- à partir d'HTML5 -- manipuler le contenu de l'ensemble de l'historique.</p> + +<h2 id="Se_déplacer_dans_l'historique">Se déplacer dans l'historique</h2> + +<p>Avancer ou reculer dans l'historique de l'utilisateur est possible en utilisant les méthodes <code>back()</code>, <code>forward()</code> et <code>go()</code>.</p> + +<h3 id="Avancer_et_reculer">Avancer et reculer</h3> + +<p>Pour reculer dans l'historique, il vous suffit de faire :</p> + +<pre class="brush: js">window.history.back(); +</pre> + +<p>Cela agira exactement comme si l'utilisateur cliquait sur le bouton Retour de la barre d'outils de son navigateur.</p> + +<p>De la même manière, il est possible d'avancer (comme si l'utilisateur cliquait sur le bouton Avancer) :</p> + +<pre class="brush: js">window.history.forward(); +</pre> + +<h3 id="Se_déplacer_à_un_élément_précis_de_l'historique">Se déplacer à un élément précis de l'historique</h3> + +<p>Vous pouvez utiliser la méthode <code>go()</code> pour charger une page spécifique de l'historique de la session, identifiée par sa position relative par rapport à la page en cours (la page courante étant, évidemment, d'index 0).</p> + +<p>Pour reculer d'une page (l'équivalent d'un appel à <code>back()</code>):</p> + +<pre class="brush: js"><code>window.history.go(-1);</code> +</pre> + +<p>Pour avancer d'une page, comme en appelant <code>forward()</code>:</p> + +<pre class="brush: js"><code>window.history.go(1);</code> +</pre> + +<p>De la même manière, vous pouvez avancer de 2 pages en passant la valeur 2, et ainsi de suite.</p> + +<p>Vous pouvez déterminer le nombre de pages de l'historique en accédant à la valeur de la propriété length (<em>longeur</em>) :</p> + +<pre class="brush: js">var numberOfEntries = window.history.length; +</pre> + +<div class="note"><strong>Note:</strong> Internet Explorer supporte le passage d'une URL sous forme de chaîne de caractères comme paramètre de la méthode <code>go()</code>; ce comportement est non standard et non supporté par Gecko.</div> + +<h2 id="Ajouter_et_modifier_des_entrées_de_l'historique">Ajouter et modifier des entrées de l'historique</h2> + +<p>{{ gecko_minversion_header("2") }}</p> + +<p>HTML5 a introduit les méthodes <a href="/fr/docs/Web/Guide/DOM/Manipuler_historique_du_navigateur#La_méthode_pushState()">history.pushState()</a> et <a href="/fr/docs/Web/Guide/DOM/Manipuler_historique_du_navigateur#La_méthode_replaceState()">history.replaceState()</a>, qui permettent, respectivement, d'ajouter et de modifier des entrées de l'historique. Ces méthodes fonctionnent conjointement avec l'événement <a href="/fr/docs/Web/API/WindowEventHandlers/onpopstate">onpopstate</a>.</p> + +<p>L'utilisation de <code>history.pushState()</code> change le référent créé habituellement dans l'en-tête HTTP pour les objets <a href="/en/DOM/XMLHttpRequest" title="en/XMLHttpRequest"><code>XMLHttpRequest</code></a>, chaque fois que son état a été changé. Le référent sera l'URL de la page dont l'objet window est <code>this</code> au moment de la création de l'objet <a href="/en/DOM/XMLHttpRequest" title="en/XMLHttpRequest"><code>XMLHttpRequest</code></a>.</p> + +<h3 id="Exemple_de_la_méthode_pushState()"><a id="Exemple de la méthode pushState()" name="Exemple de la méthode pushState()"></a>Exemple de la méthode pushState()</h3> + +<p>Supposons que <span class="nowiki">http://mozilla.org/foo.html</span> exécute la séquence JavaScript suivante :</p> + +<pre class="brush: js">var stateObj = { foo: "bar" }; +history.pushState(stateObj, "page 2", "bar.html"); +</pre> + +<p>Cela va provoquer l'apparition dans la barre de navigation de <span class="nowiki">http://mozilla.org/bar.html</span>, mais ne provoquera pas le chargement effectif de <code>bar.html</code> ni même le test d'existence de <code>bar.html</code>.</p> + +<p>Supposons à présent que l'utilisateur accède à la page <span class="nowiki">http://google.com</span>, puis clique sur l'icône "Recul". La barre de navigation va alors afficher <span class="nowiki">http://mozilla.org/bar.html</span>, et si vous lisez l'<code>history.state</code>, vous obtiendrez le <code>stateObj</code>. L'événement <code>popstate</code> ne sera pas lancé car la page a été rechargée. La page elle-même ressemblera à <code>bar.html</code>.</p> + +<p>Si on clique à nouveau sur Recul, l'URL de la barre de navigation va se changer en <span class="nowiki">http://mozilla.org/foo.html</span> et le document va recevoir un autre événement <code>popstate</code>, qui comportera, cette fois, un état null. Dans ce cas aussi, revenir en arrière ne modifie pas le contenu du document par rapport à ce qu'il était à l'étape précédente, cela bien qu'il ait pu être mis à jour manuellement sur réception de l'événement <code>popstate</code>.</p> + +<h3 id="La_méthode_pushState()">La méthode pushState()</h3> + +<p><code>La méthode pushState()</code> utilise trois paramètres : un objet état, un titre (qui est pour l'instant ignoré) et, éventuellement, une URL. Examinons chacun de ces paramètres en détail :</p> + +<ul> + <li> + <p><strong>state object</strong> (<em><strong>objet état</strong></em>) — L'objet état est un objet JavaScript qui est associé à une nouvelle entrée de l'historique par <code>pushState()</code>. Chaque fois qu'un utilisateur ouvre une nouvelle page, un événement <code>popstate</code> est émis et la propriété <code>state</code> de l'événement contient une copie de l'objet état de ce nouvel élément de l'historique.<br> + L'objet état peut être tout ce qui peut être sous forme de liste. Puisque Firefox sauvegarde les objets état sur le disque de l'utilisateur de façon à ce qu'ils puissent être rétablis après redémarrage du navigateur, le codage de l'objet état est limité à une taille de 640k octets. Si vous donnez à <code>pushState()</code> un objet état dont la représentation a une taille plus importante, la méthode génèrera une exception. Si vous avez un besoin d'espace plus important, il est conseillé d'utiliser <code>sessionStorage</code> et/ou <code>localStorage</code>.</p> + </li> + <li> + <p><strong>title</strong> (<strong><em>titre</em>)</strong> — Firefox, pour l'instant, ignore ce paramètre, bien qu'il puisse être utilisé plus tard. Afin de prévenir les changements futurs de cette méthode, il serait prudent de fournir ici, en paramètre, une chaîne vide. Vous pourriez aussi donner un titre court à l'état vers lequel vous vous dirigez.</p> + </li> + <li> + <p><strong>URL</strong> — L'URL de la nouvelle entrée de l'historique est donnée par ce paramètre. Il convient de préciser que le navigateur n'essaiera pas de charger la page pointée par cette URL après un appel à <code>pushState()</code>, mais il se peut qu'il tente de le faire plus tard, par exemple, lorsque l'utilisateur relancera son navigateur. Il n'est pas nécessaire que la nouvelle URL soit absolue ; si elle est relative, ce sera par rapport à l'URL courante. La nouvelle URL doit avoir la même origine (domaine) que l'URL courante ; dans le cas contraire, <code>pushState()</code> génèrera une exception. Ce paramètre est optionnel ; s'il n'est pas spécifié, sa valeur par défaut est l'URL de la page courante.</p> + </li> +</ul> + +<div class="note"><strong>Note :</strong> Dans Gecko 2.0 {{ geckoRelease("2.0") }} jusqu'à Gecko 5.0 {{ geckoRelease("5.0") }}, l'objet fourni est sérialisé en utilisant JSON. À partir de Gecko 6.0 {{ geckoRelease("6.0") }}, l'objet est sérialisé à l'aide de<a href="/en/DOM/The_structured_clone_algorithm" title="en/DOM/The structured clone algorithm"> "structured clone algorithm"</a> qui autorise, en particulier, la sérialisation d'arbres récursifs cycliques. Cela permet de passer de façon sûre une plus grande diversité d'objets.</div> + +<p>On peut assimiler l'appel à <code>pushState()</code> à l'affectation <code>window.location = "#foo"</code>, en cela que l'un comme l'autre auront pour effet de créer et déclencher une autre entrée de l'historique associée au document courant. Mais <code>pushState()</code> a quelques avantages :</p> + +<ul> + <li>La nouvelle URL peut être quelconque pourvu qu'elle ait la même origine que l'URL courante. En revanche, affecter <code>window.location</code> vous maintient au même {{ domxref("document") }} seulement si vous modifiez uniquement le hash.</li> + <li>Vous n'êtes pas contraint de modifier l'URL si vous ne le voulez pas. Par contre, affecter <code>window.location = "#foo";</code> crée une nouvelle entrée de l'historique seulement si le hash courant n'est pas <code>#foo</code>.</li> + <li>Vous pouvez associer des données quelconques avec votre nouvelle entrée de l'historique. Avec l'approche basée sur le hash, il est nécessaire de coder toute donnée pertinente en une chaîne courte.</li> +</ul> + +<p>Notez que <code>pushState()</code> n'entraîne jamais le déclenchement d'un événement <code>hashchange</code>, même si la nouvelle URL diffère de l'ancienne seulement par son hash.</p> + +<p>Dans un document <a href="https://developer.mozilla.org/fr/docs/Mozilla/Tech/XUL">XUL</a> elle crée l'élément XUL spécifié.</p> + +<p>Dans d'autres documents, elle crée un élément avec l'URI d'espace de nom <code>null</code>. </p> + +<h3 id="La_méthode_replaceState()">La méthode replaceState()</h3> + +<p><code>history.replaceState()</code> fonctionne exactement comme <code>history.pushState()</code> hormis le fait que <code>replaceState()</code> modifie l'entrée courante de l'historique au lieu d'en créer une nouvelle. À noter que ceci n'empêche pas la création d'une nouvelle entrée dans l'historique global du navigateur.</p> + +<p><code>replaceState()</code> est particulièrement utile si vous désirez mettre à jour l'objet état ou l'URL de l'entrée courante de l'historique en réponse à une action de l'utilisateur.</p> + +<div class="note"><strong>Note :</strong> Dans Gecko 2.0 {{ geckoRelease("2.0") }} jusqu'à Gecko 5.0 {{ geckoRelease("5.0") }}, l'objet transmis est sérialisé avec JSON. À partir de Gecko 6.0 {{ geckoRelease("6.0") }}, l'objet est sérialisé à l'aide de<a href="/en/DOM/The_structured_clone_algorithm" title="en/DOM/The structured clone algorithm"> "structured clone algorithm"</a> qui autorise, en particulier, la sérialisation d'arbres récursifs cycliques. Cela permet de passer de façon sûre une plus grande diversité d'objets.</div> + +<h3 id="Exemple_de_la_méthode_replaceState()">Exemple de la méthode replaceState()</h3> + +<p><span id="result_box" lang="fr"><span>Supposons que http://mozilla.org/foo.html exécute le code JavaScript suivant :</span></span></p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">var</span> stateObj <span class="operator token">=</span> <span class="punctuation token">{</span> foo<span class="punctuation token">:</span> <span class="string token">"bar"</span> <span class="punctuation token">}</span><span class="punctuation token">;</span> +history<span class="punctuation token">.</span><span class="function token">pushState</span><span class="punctuation token">(</span>stateObj<span class="punctuation token">,</span> <span class="string token">"page 2"</span><span class="punctuation token">,</span> <span class="string token">"bar.html"</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<p>L'explication des deux lignes ci-dessus peut être trouvée dans la section "<a href="#">Exemple de la méthode pushState()</a>". Supposons ensuite que http://mozilla.org/bar.html exécute le code JavaScript suivant :</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js">history<span class="punctuation token">.</span><span class="function token">replaceState</span><span class="punctuation token">(</span>stateObj<span class="punctuation token">,</span> <span class="string token">"page 3"</span><span class="punctuation token">,</span> <span class="string token">"bar2.html"</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<p>Cela entraînera l'affichage de la barre d'URL http://mozilla.org/bar2.html, mais le navigateur ne chargera pas <code>bar2.html</code> ou même vérifiera que <code>bar2.html</code> existe.</p> + +<p>Supposons maintenant que l'utilisateur accède à http://www.microsoft.com, puis clique sur le bouton Précédent. À ce stade, la barre d'URL affichera http://mozilla.org/bar2.html. Si l'utilisateur clique à nouveau sur Retour, la barre d'URL affichera http://mozilla.org/foo.html et contournera totalement bar.html.</p> + +<h3 id="L'événement_popstate">L'événement popstate</h3> + +<p>Un événement <code>popstate</code> est envoyé à la fenêtre chaque fois que l'entrée active de l'historique change. Si l'entrée de l'historique activée a été créée par un appel à <code>replaceState</code>, la propriété <code>state </code>de l'événement <code>popstate</code> contient une copie de l'objet état de l'entrée de l'historique.</p> + +<p>Voir {{ domxref("window.onpopstate") }} pour un exemple d'utilisation.</p> + +<h3 id="Lire_l'état_courant">Lire l'état courant</h3> + +<p>Quand votre page est chargée, il se pourrait qu'elle ait un objet état non nul. Cela peut se produire, par exemple, si la page fixe un objet état (avec <code>pushState()</code> ou <code>replaceState()</code>) et qu'ensuite l'utilisateur redémarre le navigateur. Quand votre page sera rechargée, elle recevra l'événement <span style="font-family: courier new;">onload</span><span style="font-family: helvetica;"> , mais pas l'événement <span style="font-family: courier new;">popstate</span>.</span> Néanmoins, si vous lisez la propriété <span style="font-family: courier new;">history.state</span>, vous récupèrerez l'objet état que vous auriez obtenu si un événement <span style="font-family: courier new;">popstate</span> avait été déclenché.</p> + +<p>Vous pouvez lire l'état de l'entrée courante de l'historique sans devoir attendre un événement <code>popstate</code> en utilisant la propriété <code>history.state</code> comme ceci :</p> + +<pre class="brush: js">var currentState = history.state; +</pre> + +<h2 id="Exemples">Exemples</h2> + +<p>Pour un exemple comple de site web AJAX, vous pouvez voir : <a href="https://developer.mozilla.org/fr/docs/Web/Guide/DOM/Manipuler_historique_du_navigateur/Example" title="/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history/Example">Exemple de navigation en Ajax</a>.</p> + +<h2 id="Spécifications">Spécifications</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Spécification</th> + <th scope="col">Statut</th> + <th scope="col">Commentaire</th> + </tr> + <tr> + <td>{{SpecName('HTML WHATWG', "browsers.html#history", "History")}}</td> + <td>{{Spec2('HTML WHATWG')}}</td> + <td>Pas de changement de {{SpecName("HTML5 W3C")}}.</td> + </tr> + <tr> + <td>{{SpecName('HTML5 W3C', "browsers.html#history", "History")}}</td> + <td>{{Spec2('HTML5 W3C')}}</td> + <td>Définition initiale.</td> + </tr> + </tbody> +</table> + +<h2 id="Compatibilité_des_navigateurs">Compatibilité des navigateurs</h2> + +<p>{{ CompatibilityTable() }}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Fonctionnalité</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>replaceState, pushState</td> + <td>5</td> + <td>{{ CompatGeckoDesktop("2.0") }}</td> + <td>10</td> + <td>11.50</td> + <td>5.0</td> + </tr> + <tr> + <td>history.state</td> + <td>18</td> + <td>{{ CompatGeckoDesktop("2.0") }}</td> + <td>10</td> + <td>11.50</td> + <td>{{ CompatNo() }}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Fonctionnalité</th> + <th>Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>replaceState, pushState</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + <tr> + <td>history.state</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + </tbody> +</table> +</div> + +<p>Vous pouvez utiliser <a class="link-https" href="https://github.com/browserstate/history.js" title="https://github.com/balupton/history.js">History.js</a> pour contourner les <a class="link-https" href="https://github.com/balupton/history.js/wiki/The-State-of-the-HTML5-History-API" title="https://github.com/balupton/history.js/wiki/The-State-of-the-HTML5-History-API">problèmes</a> de compatibilité entre navigateurs.</p> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li>{{ domxref("window.history") }}</li> + <li>{{ domxref("window.onpopstate") }}</li> +</ul> diff --git a/files/fr/web/guide/dom/using_full_screen_mode/index.html b/files/fr/web/guide/dom/using_full_screen_mode/index.html new file mode 100644 index 0000000000..76144c64f2 --- /dev/null +++ b/files/fr/web/guide/dom/using_full_screen_mode/index.html @@ -0,0 +1,301 @@ +--- +title: Utiliser le mode plein écran +slug: Web/Guide/DOM/Using_full_screen_mode +tags: + - API + - DOM + - Plein écran + - Tutoriel +translation_of: Web/API/Fullscreen_API +--- +<p>{{DefaultAPISidebar("Fullscreen API")}}</p> + +<p class="summary">L'<strong>API Fullscreen</strong> <em>(plein écran)</em> fournit un moyen simple de présenter du contenu web en utilisant l'ensemble de l'écran de l'utilisateur. <span id="result_box" lang="fr"><span>L'API vous permet de diriger facilement le navigateur pour faire en sorte qu'un élément et ses enfants, le cas échéant, occupent entièrement l'écran, éliminant toute l'interface utilisateur du navigateur et les autres applications de l'écran pendant ce temps.</span></span></p> + +<div class="note"><strong>Note :</strong> Pour le moment, tous les navigateurs n'utilisent pas la version non préfixée de cet API. <span id="result_box" lang="fr"><span>Consultez le tableau récapitulant les <a href="#Préfixes">préfixes</a> et les différences de noms entre eux (vous pouvez également utiliser </span></span> <a href="https://github.com/rafrex/fscreen">Fscreen</a> <span lang="fr"><span> pour l'accès du fournisseur à l'API).</span></span></div> + +<h2 id="Specification" name="Specification">Activation du mode plein écran</h2> + +<p>En partant d'un élément que vous aimeriez afficher en plein écran ({{ HTMLElement("video") }}, par exemple), vous pouvez le passer en mode plein écran simplement en appelant sa méthode {{ domxref("Element.requestFullscreen()") }} .</p> + +<p>Prenons cet élément {{ HTMLElement("video") }} :</p> + +<pre class="brush: html"><video controls id="myvideo"> + <source src="somevideo.webm"></source> + <source src="somevideo.mp4"></source> +</video> +</pre> + +<p>Nous pouvons mettre cet élément video en plein écran avec un script de cette façon :</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">var</span> elem <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">getElementById</span><span class="punctuation token">(</span><span class="string token">"myvideo"</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="keyword token">if</span> <span class="punctuation token">(</span>elem<span class="punctuation token">.</span>requestFullscreen<span class="punctuation token">)</span> <span class="punctuation token">{</span> + elem<span class="punctuation token">.</span><span class="function token">requestFullscreen</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<h3 id="Différences_de_présentation">Différences de présentation</h3> + +<p>Il est important de savoir qu'il y a une différence clef entre les implémentations de Gecko et WebKit : Gecko ajoute automatiquement des règles CSS à l'élément afin qu'il remplisse l'écran : "<code>width: 100%; height: 100%</code>". WebKit ne fait pas ça ; à la place, il centre l'élément sans le redimensionner au milieu d'un écran noir. Pour obtenir le même comportement que Gecko dans WebKit, vous devez ajouter votre propre règle "<code>width: 100%; height: 100%;</code>" à l'élément :</p> + +<pre class="brush: css">#myvideo:-webkit-full-screen { + width: 100%; + height: 100%; +} +</pre> + +<p>Dans l'autre sens, si vous essayez d'émuler le comportement de WebKit sur Gecko, vous devez placer l'élément que vous souhaitez présenter dans un autre élément, que vous mettrez en plein écran, et utiliser des règles CSS pour ajuster l'apparence de l'élément interne.</p> + +<h3 id="Notification">Notification</h3> + +<p>Quand le mode plein écran est activé, le document qui contient l'élément reçoit un événement de type {{ event("fullscreenchange") }} . Lors de la sortie du mode plein écran, le document reçoit à nouveau l'événement {{ event("fullscreenchange") }} . Notez que l'événement en lui-même {{ event("fullscreenchange") }} ne fournit aucune information si le document est en train d'entrer ou de sortir du mode plein écran, mais si le document a une valeur non nulle {{ domxref("document.fullscreenElement", "fullscreenElement") }} , vous savez que vous êtes en mode plein écran.</p> + +<h3 id="Lorsqu'une_demande_de_plein_écran_échoue">Lorsqu'une demande de plein écran échoue</h3> + +<p>Il n'est pas garanti que vous soyez capable de passer en mode plein écran. Par exemple, les élements {{ HTMLElement("iframe") }} possèdent l'attribut {{ HTMLAttrXRef("allowfullscreen", "iframe") }} pour permettre à leur contenu d'être affiché en mode plein écran. Certains contenus comme les greffons fenêtrés ne peuvent être représentés en plein écran. Essayer de placer un élément qui ne peut être affiché en mode plein écran (ou le parent ou le descendant d'un tel élément) ne marchera pas. A la place, l'élément qui a demandé le mode plein écran recevra un événement <code>mozfullscreenerror</code> . Quand une demande de plein écran échoue, Firefox écrit un message d'erreur dans la console Web expliquant pourquoi la demande n'a pas pu aboutir. <span id="result_box" lang="fr"><span>Dans Chrome et les versions plus récentes d'Opera, aucun avertissement de ce type n'est généré.</span></span></p> + +<div class="note"> +<p><strong>Note :</strong> Les requêtes de Fullscreen doivent être appelées depuis un gestionnaire d'évènements ou sinon, elles seront refusées.</p> +</div> + +<h2 id="Sortie_du_mode_plein_écran">Sortie du mode plein écran</h2> + +<p>L'utilisateur peut toujours sortir du mode plein écran quand il le désire ; voir {{ anch("Choses que vos utilisateurs doivent savoir") }}. Vous pouvez également le faire en appelant la méthode {{domxref("Document.exitFullscreen()")}} .</p> + +<h2 id="Autres_informations">Autres informations</h2> + +<p>Le {{ domxref("document") }} fournit des informations supplémentaires pouvant être utiles lorsque vous développez des applications web en plein écran :</p> + +<dl> + <dt>{{ domxref("document.fullscreenElement", "fullscreenElement") }}</dt> + <dd>L'attribut <code>fullscreenElement</code> vous indique l'{{ domxref("element") }} qui est actuellement affiché en plein écran. S'il est non nul, le document est en mode plein écran. S'il est nul, le document n'est pas en mode plein écran.</dd> + <dt>{{ domxref("document.fullscreenEnabled", "fullscreenEnabled") }}</dt> + <dd>L'attribut <code>fullscreenEnabled</code> vous indique si le document est actuellement dans un état qui permettrait d'activer le mode plein écran ou non.</dd> +</dl> + +<h2 id="Things_your_users_want_to_know" name="Things_your_users_want_to_know">Choses que vos utilisateurs doivent savoir</h2> + +<p>Vous voulez faire savoir à vos utilisateurs qu'il peuvent utiliser la touche <kbd>ECHAP</kbd> (ou <kbd>F11</kbd>) pour sortir du mode plein écran.</p> + +<p>En même temps, naviguer sur une autre page, changer d'onglet, ou changer d'application (en utilisant, par exemple, <kbd>Alt</kbd>-<kbd>Tab</kbd> ) pendant le mode plein écran, implique la sortie du mode plein écran de toute façon.</p> + +<h2 id="Specification" name="Specification">Exemple</h2> + +<p>Dans cet exemple, une vidéo est affichée dans une page web. Taper sur l'une des touches <kbd>Retour</kbd> ou <kbd>Entrée</kbd>, permet à l'utilisateur de passer d'une présentation dans une fenêtre à une présentation en mode plein écran de la vidéo.</p> + +<p><a href="/samples/domref/fullscreen.html">Voir l'exemple sur une page</a></p> + +<h3 id="Action_sur_la_touche_Entrée">Action sur la touche <kbd>Entrée</kbd></h3> + +<p>Quand la page est chargée, ce code est exécuté pour mettre en place un évènement "listener" permettant de surveiller la moindre action sur la touche <kbd>Entrée</kbd> .</p> + +<pre class="brush: js">document.addEventListener("keydown", function(e) { + if (e.keyCode == 13) { + toggleFullScreen(); + } +}, false); +</pre> + +<h3 id="Passer_en_mode_plein_écran">Passer en mode plein écran</h3> + +<p>Ce code est appelé lorsque l'utilisateur appuie sur la touche <kbd>Entrée</kbd>, comme vu plus haut.</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">function</span> <span class="function token">toggleFullScreen</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="keyword token">if</span> <span class="punctuation token">(</span><span class="operator token">!</span>document<span class="punctuation token">.</span>fullscreenElement<span class="punctuation token">)</span> <span class="punctuation token">{</span> + document<span class="punctuation token">.</span>documentElement<span class="punctuation token">.</span><span class="function token">requestFullscreen</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> <span class="keyword token">else</span> <span class="punctuation token">{</span> + <span class="keyword token">if</span> <span class="punctuation token">(</span>document<span class="punctuation token">.</span>exitFullscreen<span class="punctuation token">)</span> <span class="punctuation token">{</span> + document<span class="punctuation token">.</span><span class="function token">exitFullscreen</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> + <span class="punctuation token">}</span> +<span class="punctuation token">}</span></code></pre> + +<p> Dans un premier temps, la valeur de l'attribut <code>fullscreenElement</code> est analysée dans le {{ domxref("document") }} (en contrôlant s'il est préfixé par <code>moz-, ms-</code> ou <code>webkit-</code>). Si la valeur est nulle, le document est actuellement en mode normal, donc nous devons passer en mode plein écran. Le passage en mode plein écran est assuré en appelant {{ domxref("element.requestFullscreen()") }}.</p> + +<p>Si le mode plein écran est déjà activé (<code>fullscreenElement</code> est non nul), nous appelons {{ domxref("document.exitFullscreen()") }}.</p> + +<h2 id="Préfixes_2"><a name="Préfixes">Préfixes</a></h2> + +<p>Pour le moment, tous les navigateurs n'ont pas implémenté la version sans préfixe de l'API (pour l'accès du fournisseur de l'API, vous pouvez utiliser <a href="https://github.com/rafrex/fscreen">Fscreen</a>) . <span id="result_box" lang="fr"><span>Voici le tableau résumant les préfixes et les différences de noms entre eux </span></span><span lang="fr"><span>:</span></span></p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Standard</th> + <th scope="col">Blink (Chrome & Opera)</th> + <th scope="col">Gecko (Firefox)</th> + <th scope="col">Internet Explorer 11</th> + <th scope="col">Edge</th> + <th scope="col">Safari (WebKit)</th> + </tr> + <tr> + <td>{{domxref("Document.fullscreen")}}</td> + <td><code>webkitIsFullScreen</code></td> + <td><code>mozFullScreen</code></td> + <td><em>-</em></td> + <td><code>webkitIsFullScreen</code></td> + <td><code>webkitIsFullScreen</code></td> + </tr> + <tr> + <td>{{domxref("Document.fullscreenEnabled")}}</td> + <td><code>webkitFullscreenEnabled</code></td> + <td><code>mozFullScreenEnabled</code></td> + <td><code>msFullscreenEnabled</code></td> + <td><code>webkitFullscreenEnabled</code></td> + <td><code>webkitFullscreenEnabled</code></td> + </tr> + <tr> + <td>{{domxref("Document.fullscreenElement")}}</td> + <td><code>webkitFullscreenElement</code></td> + <td><code>mozFullScreenElement</code></td> + <td><code>msFullscreenElement</code></td> + <td><code>webkitFullscreenElement</code></td> + <td><code>webkitFullscreenElement</code></td> + </tr> + <tr> + <td>{{domxref("Document.onfullscreenchange")}}</td> + <td><code>onwebkitfullscreenchange</code></td> + <td><code>onmozfullscreenchange</code></td> + <td><code>MSFullscreenChange</code></td> + <td><code>onwebkitfullscreenchange</code></td> + <td><code>onwebkitfullscreenchange</code></td> + </tr> + <tr> + <td>{{domxref("Document.onfullscreenerror")}}</td> + <td><code>onwebkitfullscreenerror</code></td> + <td><code>onmozfullscreenerror</code></td> + <td><code>MSFullscreenError</code></td> + <td><code>onwebkitfullscreenerror</code></td> + <td><code>onwebkitfullscreenerror</code></td> + </tr> + <tr> + <td>{{domxref("Document.exitFullscreen()")}}</td> + <td><code>webkitExitFullscreen()</code></td> + <td><code>mozCancelFullScreen()</code></td> + <td><code>msExitFullscreen()</code></td> + <td><code>webkitExitFullscreen()</code></td> + <td><code>webkitExitFullscreen()</code></td> + </tr> + <tr> + <td>{{domxref("Element.requestFullscreen()")}}</td> + <td><code>webkitRequestFullscreen()</code></td> + <td><code>mozRequestFullScreen()</code></td> + <td><code>msRequestFullscreen()</code></td> + <td><code>webkitRequestFullscreen()</code></td> + <td><code>webkitRequestFullscreen()</code></td> + </tr> + </thead> +</table> + +<h2 id="Specification" name="Specification">Spécifications</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Specification</th> + <th scope="col">Statut</th> + <th scope="col">Commentaire</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName("Fullscreen")}}</td> + <td>{{Spec2("Fullscreen")}}</td> + <td>Définition initiale.</td> + </tr> + </tbody> +</table> + +<h2 id="BrowserCompatibility" name="BrowserCompatibility">Compatibilité des navigateurs</h2> + +<p><span id="result_box" lang="fr"><span>Tous les navigateurs implémentent cette API.</span> <span>Néanmoins certains l'implémentent avec des préfixes avec des noms légèrement différents</span></span> <span id="result_box" lang="fr"><span>;</span> <span>par exemple, au lieu de <code>requestFullscreen ()</code>, il y a <code>MozRequestFullScreen ()</code>.</span></span></p> + +<p>{{ CompatibilityTable() }} </p> + +<div id="compat-mobile"> +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Fonctionnalité</th> + <th>Chrome</th> + <th>Edge</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>15 {{ property_prefix("-webkit") }}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{ CompatGeckoDesktop("9.0") }} {{ property_prefix("-moz") }}<br> + {{CompatGeckoDesktop("47")}} (behind <code>full-screen-api.unprefix.enabled</code>)</td> + <td>11 {{ property_prefix("-ms") }}</td> + <td>12.10</td> + <td>5.0 {{ property_prefix("-webkit") }}</td> + </tr> + <tr> + <td><code>fullscreenEnabled</code></td> + <td>20 {{ property_prefix("-webkit") }}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{ CompatGeckoDesktop("10.0") }} {{ property_prefix("-moz") }}<br> + {{CompatGeckoDesktop("47")}} (behind <code>full-screen-api.unprefix.enabled</code>)</td> + <td>11 {{ property_prefix("-ms") }}</td> + <td>12.10</td> + <td>5.1 {{ property_prefix("-webkit") }}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Fonctionnalité</th> + <th>Android</th> + <th>Chrome</th> + <th>Edge</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{ CompatUnknown() }}</td> + <td>28 {{ property_prefix("-webkit") }}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{ CompatGeckoMobile("9.0") }}{{ property_prefix("-moz") }}<br> + {{CompatGeckoMobile("47")}} (behind <code>full-screen-api.unprefix.enabled</code>)</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + <tr> + <td><code>fullscreenEnabled</code></td> + <td>{{ CompatUnknown() }}</td> + <td>28 {{ property_prefix("-webkit") }}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{ CompatGeckoMobile("10.0") }} {{ property_prefix("moz") }}<br> + {{CompatGeckoMobile("47")}} (behind <code>full-screen-api.unprefix.enabled</code>)</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + </tbody> +</table> +</div> +</div> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li><a href="https://developer.mozilla.org/fr/docs/Web/Guide/DOM/Using_full_screen_mode">Utiliser le mode plein écran</a></li> + <li>{{ domxref("Element.requestFullscreen()") }}</li> + <li>{{ domxref("Document.exitFullscreen()") }}</li> + <li>{{ domxref("Document.fullscreen") }}</li> + <li>{{ domxref("Document.fullscreenElement") }}</li> + <li>{{ cssxref(":fullscreen") }}, {{cssxref("::backdrop")}}</li> + <li>{{ HTMLAttrXRef("allowfullscreen", "iframe") }}</li> +</ul> diff --git a/files/fr/web/guide/graphics/dessiner_avec_canvas/index.html b/files/fr/web/guide/graphics/dessiner_avec_canvas/index.html new file mode 100644 index 0000000000..5799de096f --- /dev/null +++ b/files/fr/web/guide/graphics/dessiner_avec_canvas/index.html @@ -0,0 +1,175 @@ +--- +title: Dessiner avec Canvas +slug: Web/Guide/Graphics/Dessiner_avec_canvas +tags: + - Canvas + - HTML +translation_of: Web/API/Canvas_API/Tutorial +--- +<p> </p> +<h3 id="Introduction" name="Introduction">Introduction</h3> +<p>Depuis <a href="/fr/Firefox_1.5_pour_les_d%C3%A9veloppeurs" title="fr/Firefox_1.5_pour_les_développeurs">Firefox 1.5</a>, Firefox comprend un nouvel élément HTML servant à dessiner programmatiquement. L'élément {{HTMLElement("canvas")}} est basé sur la <a class="external" href="http://www.whatwg.org/specs/web-apps/current-work/#the-canvas">spécification canvas du WHATWG</a>, elle-même basée sur la balise <code><canvas></code> d'Apple implémentée dans Safari. Celui-ci peut être utilisé pour afficher des graphes, des élements d'interface, et d'autres éléments graphiques personnalisés sur le client.</p> +<p>{{HTMLElement("canvas")}} crée une surface de dessin de taille fixe, ou <em>canevas</em>, exposant un ou plusieurs <em>contextes de rendu</em>. Nous nous concentrerons sur le contexte de rendu 2D (c'est d'ailleurs le seul contexte de rendu actuellement défini). Dans le futur, d'autres contextes peuvent fournir différents types de rendu. Par exemple, il est probable qu'un contexte 3D basé sur OpenGL ES sera ajouté à la spécification <code><canvas></code>.</p> +<h3 id="Le_contexte_de_rendu_2D" name="Le_contexte_de_rendu_2D">Le contexte de rendu 2D</h3> +<h4 id="Un_exemple_simple" name="Un_exemple_simple">Un exemple simple</h4> +<p>Pour commencer, voici un exemple simple qui dessine deux rectangles ayant une intersection, l'un d'entre-eux possédant une transparence alpha :</p> +<p><img align="right" alt="Exemple 1." class="internal" src="/@api/deki/files/1337/=Canvas_ex1.png"></p> +<pre class="eval"><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> +</pre> +<p>La fonction <code>draw</code> récupère l'élément <code>canvas</code>, et ensuite son contexte <code>2d</code>. L'objet <code>ctx</code> peut ensuite être utilisé pour dessiner réellement vers le canevas. L'exemple remplit simplement les deux rectangles, en positionnant <code>fillStyle</code> à deux couleurs différentes à l'aide des spécifications de couleur CSS et d'un appel à <code>fillRect</code>. Le second appel à <code>fillStyle</code> utilise <code>rgba()</code> pour spécifier une valeur alpha parmi les informations de couleur.</p> +<p>Les appels à <code>fillRect</code>, <code>strokeRect</code> et <code>clearRect</code> affichent un rectangle plein, surligné ou vide. Pour afficher des formes plus complexes, on utilise des chemins.</p> +<h4 id="Utilisation_de_chemins" name="Utilisation_de_chemins">Utilisation de chemins</h4> +<p>La fonction <code>beginPath</code> commence un nouveau chemin, et <code>moveTo</code>, <code>lineTo</code>, <code>arcTo</code>, <code>arc</code> et des méthodes similaires sont utilisées pour ajouter des segments au chemin. Le chemin peut être fermé à l'aide de <code>closePath</code>. Une fois que le chemin est créé, vous pouvez utiliser <code>fill</code> ou <code>stroke</code> pour afficher celui-ci sur le canevas.</p> +<p><img align="right" alt="Exemple 2." class="internal" src="/@api/deki/files/1338/=Canvas_ex2.png"></p> +<pre class="eval"><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> +</pre> +<p>L'appel à <code>fill()</code> ou <code>stroke()</code> provoque l'utilisation du chemin. Pour être rempli ou dessiné à nouveau, le chemin devra être recréé.</p> +<h4 id=".C3.89tat_graphique" name=".C3.89tat_graphique">État graphique</h4> +<p>Les attributs du contexte comme <code>fillStyle</code>, <code>strokeStyle</code>, <code>lineWidth</code> et <code>lineJoin</code> font partie de l'<em>état graphique</em> courant. Le contexte fournit deux méthodes, <code>save()</code> et <code>restore()</code>, qui peuvent être utilisées pour déplacer l'état courant vers et depuis la pile d'états.</p> +<h4 id="Un_exemple_plus_compliqu.C3.A9" name="Un_exemple_plus_compliqu.C3.A9">Un exemple plus compliqué</h4> +<p>Voici un exemple un petit peu plus compliqué, qui utilise des chemins, des états et introduit également la matrice de transformation courante. Les méthodes du contexte <code>translate()</code>, <code>scale()</code> et <code>rotate()</code> transforment toutes la matrice courante. Tous les points affichés sont au préalable transformés par cette matrice.</p> +<p><img align="right" alt="Exemple 3." class="internal" src="/@api/deki/files/1339/=Canvas_ex3.png"></p> +<pre> <html> + <head> + <script type="application/x-javascript"> + function dessineNoeudPap(ctx, fillStyle) { + + ctx.fillStyle = "rgba(200,200,200,0.3)"; + ctx.fillRect(-30, -30, 60, 60); + + ctx.fillStyle = fillStyle; + ctx.globalAlpha = 1.0; + ctx.beginPath(); + ctx.moveTo(25, 25); + ctx.lineTo(-25, -25); + ctx.lineTo(25, -25); + ctx.lineTo(-25, 25); + ctx.closePath(); + ctx.fill(); + } + + function point(ctx) { + ctx.save(); + ctx.fillStyle = "black"; + ctx.fillRect(-2, -2, 4, 4); + ctx.restore(); + } + + function dessine() { + var canvas = document.getElementById("canvas"); + var ctx = canvas.getContext("2d"); + + // notez que toutes les autres translations sont relatives à + // celle-ci + ctx.translate(45, 45); + + ctx.save(); + //ctx.translate(0, 0); // non nécessaire + dessineNoeudPap(ctx, "red"); + point(ctx); + ctx.restore(); + + ctx.save(); + ctx.translate(85, 0); + ctx.rotate(45 * Math.PI / 180); + dessineNoeudPap(ctx, "green"); + point(ctx); + ctx.restore(); + + ctx.save(); + ctx.translate(0, 85); + ctx.rotate(135 * Math.PI / 180); + dessineNoeudPap(ctx, "blue"); + point(ctx); + ctx.restore(); + + ctx.save(); + ctx.translate(85, 85); + ctx.rotate(90 * Math.PI / 180); + dessineNoeudPap(ctx, "yellow"); + point(ctx); + ctx.restore(); + } + </script> + </head> + <body onload="dessine()"> + <canvas id="canvas" width="300" height="300"></canvas> + </body> + </html> +</pre> +<p>Ceci définit deux méthodes <code>dessineNoeudPap</code> et <code>point</code>, qui sont appelées 4 fois. Avant chaque appel, <code>translate()</code> et <code>rotate()</code> sont utilisées pour définir la matrice de transformation courante, qui à son tour positionne le point et le nœud papillon. <code>point</code> affiche un petit carré noir centré sur <code>(0, 0)</code>. Ce point est déplacé par la matrice de transformation. <code>dessineNoeudPap</code> affiche un chemin simple en forme de nœud papillon en utilisant le style de remplissage fourni en paramètre.</p> +<p>Comme les opérations de matrices sont cumulatives, <code>save()</code> et <code>restore()</code> sont utilisées autour de chaque jeu d'appels afin de restaurer l'état initial du canevas. Une chose à surveiller est que la rotation se passe toujours autour de l'origine courante ; donc une séquence <code>translate() rotate() translate()</code> donnera des résultats différents d'une série d'appels <code>translate() translate() rotate()</code>.</p> +<h3 id="Compatibilit.C3.A9_avec_le_.3Ccanvas.3E_d.27Apple" name="Compatibilit.C3.A9_avec_le_.3Ccanvas.3E_d.27Apple">Compatibilité avec le <canvas> d'Apple</h3> +<p>Pour la plus grande partie, le <code><canvas></code> de Mozilla est compatible avec celui d'Apple et d'autres implémentations. Il convient cependant d'être averti de quelques problèmes, décrits ci-dessous.</p> +<h4 id="Balise_.3C.2Fcanvas.3E_requise" name="Balise_.3C.2Fcanvas.3E_requise">Balise <code></canvas></code> requise</h4> +<p>Dans l'implémentation d'Apple Safari, <code><canvas></code> est un élément fortement semblable à l'élément <code><img></code> ; il ne doit pas forcément avoir de balise de fermeture. Cependant, pour que <code><canvas></code> puisse être utilisé à grande échelle sur le Web, il est important de pouvoir fournir facilement du contenu alternatif. C'est pourquoi l'implémentation de Mozilla a une balise de fin <em>requise</em>.</p> +<p>Si aucun contenu alternatif n'est nécessaire, un simple <code><canvas id="foo" ...></canvas></code> sera entièrement compatible avec Safari et Mozilla -- Safari ignorera simplement la balise de fermeture.</p> +<p>Si un contenu alternatif est désiré, certaines astuces CSS doivent être utilisées pour masquer le contenu alternatif à Safari (qui doit seulement afficher le canevas), et masquer ces mêmes astuces à Internet Explorer (qui doit afficher le contenu alternatif). <strong>À faire : les commandes CSS exactes doivent être fournies par hixie.</strong></p> +<h3 id="Fonctionnalit.C3.A9s_suppl.C3.A9mentaires" name="Fonctionnalit.C3.A9s_suppl.C3.A9mentaires">Fonctionnalités supplémentaires</h3> +<h4 id="Affichage_de_contenu_Web_dans_un_canevas" name="Affichage_de_contenu_Web_dans_un_canevas">Affichage de contenu Web dans un canevas</h4> +<div class="note"> + Cette fonctionnalité est uniquement disponible pour le code exécuté avec des privilèges Chrome. Son utilisation n'est pas permise dans des pages HTML normales.</div> +<p>L'élément <code>canvas</code> de Mozilla a été étendu avec la méthode <code>drawWindow</code>. Celle-ci dessine une capture du contenu d'un élément DOM <code>window</code> dans le canevas. Par exemple,</p> +<pre class="eval">ctx.drawWindow(window, 0, 0, 100, 200, "rgb(0,0,0)"); +</pre> +<p>affichera le contenu de la fenêtre courante dans le rectangle (0,0,100,200) défini en pixels relatifs au coin en haut à gauche de la fenêtre d'affichage, sur un fond noir, dans le canevas. En spécifiant "rgba(0,0,0,0)" comme couleur, le contenu sera dessiné avec un fond transparent (ce qui sera plus lent).</p> +<p>Avec cette méthode, il est possible de remplir un IFRAME caché avec du contenu arbitraire (par exemple, du texte HTML stylé avec CSS, ou du SVG) et de le dessiner dans un canevas. Celui-ci sera redimensionné, tourné, etc. suivant la transformation courante.</p> +<p>L'extension <a class="external" href="http://ted.mielczarek.org/code/mozilla/tabpreview/">tab preview</a> de Ted Mielczarek utilise cette technique dans le chrome pour fournir des miniatures de pages Web, et sa source est disponible pour référence.</p> +<h3 id="Voir_aussi" name="Voir_aussi">Voir aussi</h3> +<ul> + <li><a href="/fr/HTML/Canvas" title="fr/HTML/Canvas">Page du sujet canvas</a></li> + <li><a href="/fr/Tutoriel_canvas" title="fr/Tutoriel_canvas">Tutoriel canvas</a></li> + <li><a class="external" href="http://www.whatwg.org/specs/web-apps/current-work/#the-canvas">Spécification du WHATWG</a></li> + <li><a class="external" href="http://developer.apple.com/documentation/AppleApplications/Reference/SafariJSRef/Classes/Canvas.html">La documentation d'Apple sur Canvas</a></li> + <li><a class="external" href="http://weblogs.mozillazine.org/roc/archives/2005/05/rendering_web_p.html">Affichage de miniatures de pages Web</a></li> + <li>Quelques <a href="/Special:Tags?tag=Exemples_d'utilisation_de_canvas&language=fr" title="Special:Tags?tag=Exemples_d'utilisation_de_canvas&language=fr">exemples</a> : + <ul> + <li><a class="external" href="http://www.tapper-ware.net/canvas3d/">Rendu 3D du format OBJ</a></li> + <li><a href="/fr/Un_raycaster_basique" title="fr/Un_raycaster_basique">Un raycaster basique</a></li> + <li><a class="external" href="http://awordlike.com/">The Lightweight Visual Thesaurus</a></li> + <li><a class="external" href="http://www.abrahamjoffe.com.au/ben/canvascape/">Exemple impressionnant d'utilisation de canvas</a></li> + <li><a class="external" href="http://caimansys.com/painter/">Canvas Painter</a></li> + </ul> + </li> + <li><a href="/Special:Tags?tag=HTML:Canvas&language=fr" title="Special:Tags?tag=HTML:Canvas&language=fr">Et plus…</a></li> +</ul> +<p>{{ languages( { "en": "en/Drawing_Graphics_with_Canvas", "ja": "ja/Drawing_Graphics_with_Canvas", "ko": "ko/Drawing_Graphics_with_Canvas", "pl": "pl/Rysowanie_grafik_za_pomoc\u0105_Canvas" } ) }}</p> diff --git a/files/fr/web/guide/graphics/index.html b/files/fr/web/guide/graphics/index.html new file mode 100644 index 0000000000..1581a199c1 --- /dev/null +++ b/files/fr/web/guide/graphics/index.html @@ -0,0 +1,51 @@ +--- +title: Graphismes sur le Web +slug: Web/Guide/Graphics +tags: + - 2D + - 3D + - Canvas + - Graphismes + - HTML + - SVG + - Web + - WebGL + - WebRTC +translation_of: Web/Guide/Graphics +--- +<p>Les applications et sites Web modernes ont souvent besoin de présenter des graphismes de qualité. Tandis qu'afficher de simples images statiques peut être aisément réalisé à l'aide de la balise <a href="/fr/docs/Web/HTML/Element/img"><code><img></code></a>, ou en réglant l'arrière-plan des éléments HTML avec la propriété CSS : <a href="/fr/docs/Web/CSS/background-image">background-image</a>.</p> + +<p>Mais lorsque l'on veut réaliser des graphismes à la volée, ou manipuler des images après coup, ou encore utiliser de la 3D, les méthodes habituelles ne suffisent plus, cependant avec HTML5, il est possible de réaliser ce type de graphismes plus évolués.</p> + +<p>Les articles ci-dessous vous permettront de vous familiariser avec ces technologies.</p> + +<div class="row topicpage-table"> +<div class="section"> +<h2 class="Documentation" id="Docs_for_add-on_developers" name="Docs_for_add-on_developers">Graphismes 2D</h2> + +<dl> + <dt><a href="/fr/docs/Web/Guide/Graphics/Dessiner_avec_canvas">Dessiner avec les canvas</a></dt> + <dd>Un guide d'introduction pour utiliser l'élément pour dessiner en 2D.</dd> + <dt><a href="/fr/docs/SVG">SVG</a></dt> + <dd>Scalable Vector Graphics (SVG) vous permet d'utiliser des lignes, courbes et d'autres figures géométriques pour dessiner. Les images SVG n'étant pas des images matricielles, elles permettent de faire des images redimensionnables sans limite.<span class="alllinks"><a href="/fr/docs/tag/Graphics">Tout lire...</a></span></dd> +</dl> +</div> + +<div class="section"> +<h2 class="Documentation" id="Docs_for_add-on_developers" name="Docs_for_add-on_developers">Graphismes 3D</h2> + +<dl> + <dt><a href="/fr/docs/WebGL">WebGL</a></dt> + <dd>Un guide pour débuter avec WebGL l'API graphique 3D, pour le Web. Cette technologie vous permettra d'utiliser le standard OpenGL ES pour du contenu Web.</dd> +</dl> +</div> +</div> + +<h2 class="highlight-spanned" id="Video" style="font-size: 24px !important; line-height: 30px !important;"><span class="highlight-span" style="font-size: 24px !important; line-height: 30px !important;">Video</span></h2> + +<dl style="font-size: 16px !important; line-height: 24px !important;"> + <dt style="font-size: 16px !important; line-height: 24px !important;"><a href="/fr/docs/Apprendre/HTML/Multimedia_and_embedding/Contenu_audio_et_video" style="font-size: 16px !important; line-height: 24px !important;">Utiliser les éléments HTML5 audio et video</a></dt> + <dd style="font-size: 16px !important; line-height: 24px !important;">Intégrer de la vidéo et / ou de l'audio dans une page Web</dd> + <dt style="font-size: 16px !important; line-height: 24px !important;"><a href="/fr/docs/Web/API/WebRTC_API" style="font-size: 16px !important; line-height: 24px !important;">WebRTC</a></dt> + <dd style="font-size: 16px !important; line-height: 24px !important;">Le RTC dans WebRTC est l'abréviation de Real-Time Communications, c'est une technologie qui permet le streaming audio / vidéo et le partage de données entre les clients du navigateur (homologues).</dd> +</dl> diff --git a/files/fr/web/guide/html/astuces_de_création_de_pages_html_à_affichage_rapide/index.html b/files/fr/web/guide/html/astuces_de_création_de_pages_html_à_affichage_rapide/index.html new file mode 100644 index 0000000000..58e21b4603 --- /dev/null +++ b/files/fr/web/guide/html/astuces_de_création_de_pages_html_à_affichage_rapide/index.html @@ -0,0 +1,118 @@ +--- +title: Astuces de création de pages HTML à affichage rapide +slug: Web/Guide/HTML/Astuces_de_création_de_pages_HTML_à_affichage_rapide +tags: + - HTML + - Performance +translation_of: Learn/HTML/Howto/Author_fast-loading_HTML_pages +--- +<p>C'est connu, les internautes sont de grands impatients, ils veulent des résultats immédiats, avec des gros titres et des réponses courtes et efficaces. <br> + Une page web optimisé prévoit non seulement un site plus réactif, mais aussi de réduire la charge sur vos serveurs Web et votre connexion Internet. Cela peut être crucial pour les gros sites ou des sites qui ont un pic de trafic dans des circonstances exceptionnelles (telles que les Unes des journaux fracassantes). De plus, Google en tient compte pour son classement.</p> + +<h3 id="Réduire_le_poids_de_la_page">Réduire le poids de la page</h3> + +<p>Le poids de la page est de loin le facteur le plus important dans les performances de chargement de votre page. Pour les améliorer, on peut procéder de diverses manières:</p> + +<ul> + <li>Eliminer les espaces et les commentaires inutile.</li> + <li> + <div>Déplacer le script intégré (ou "inline scripts") et le code CSS dans des fichiers externes (un pour JavaScript, un pour CSS,...). Des outils tels que <a class="external" href="http://www.html-tidy.org" title="http://tidy.sourceforge.net/">HTML Tidy</a> peuvent automatiquement enlever les espaces de trop et les lignes vides à partir d'une source HTML valide. D'autres outils peuvent "compresser" JavaScript comme le libre <a class="external" href="http://yuilibrary.com/projects/yuicompressor/" title="http://yuilibrary.com/projects/yuicompressor/">YUIcompressor</a>.</div> + </li> + <li> + <div>Verifiez que votre site ne contient pas de code inutile ou de tags superflus. </div> + </li> +</ul> + +<p>Téléchargez le html d'abords, puis le CSS et le JavaScript nécessaires à son affichage, de sorte que l'utilisateur obtienne rapidement une réponse apparente au cours du chargement de la paget. Ce contenu est généralement du texte, et peuvent donc bénéficier de la compression de texte dans le modem, fournissant ainsi une réponse encore plus rapide à l'utilisateur.</p> + +<h3 id="Réduisez_le_nombre_de_fichiers">Réduisez le nombre de fichiers</h3> + +<p>Réduire le nombre de fichiers référencés dans une page web diminue le nombre de connexions <a href="/en/HTTP" title="https://developer.mozilla.org/en/HTTP">HTTP </a>nécessaire pour télécharger une page.</p> + +<ul> + <li>Utilisez le moins d'images possible sur votre site (et de gif animés ofc). Preferez des <a class="external" href="http://css-tricks.com/examples/ButtonMaker/" title="http://css-tricks.com/examples/ButtonMaker/">boutons graphiques en CSS</a>.</li> + <li>Compressez vos images (éviter les .png). Vous pouvez pour cela utiliser <a class="external" href="http://www.gimp.org/" title="http://www.gimp.org/">Gimp</a> ou <a class="external" href="http://www.imagemagick.org/script/index.php" title="http://www.imagemagick.org/script/index.php">Imagemagik</a>.</li> + <li>Preferez le CSS ou le JavaScript au flash: il ralenti le navigateur.</li> +</ul> + +<p>Les videos sont diffusées progressivement depuis le serveur, elles ne ralentisseent donc pas le chargement de votre page.</p> + +<h3 id="Réduire_les_domaines_des_recherches">Réduire les domaines des recherches</h3> + +<p>Étant donné que chaque requete DNS demande du temps, le temps de chargement de la page va augmenter avec l'augmentation du nombre de domaines séparés figurant dans le lien CSS, JavaScript et image (src). Vous devez toujours prendre soin de n'utiliser que le nombre minimum nécessaire de différents domaines dans vos pages.</p> + +<h3 id="Réutiliser_le_contenu_du_cache">Réutiliser le contenu du cache</h3> + +<p>Assurez-vous que tout contenu qui peut être mis en cache, est mis en cache, et avec un temps d'expiration appropriée.<br> + En particulier, attention à l'en-tête "Last-Modified". Elle permet la mise en cache de la page; grâce à cette en-tête, l'information est transmise au navigateur (ou "user agent") sur le fichier qu'il veut charger, comme lors de sa dernière modification. La plupart des serveurs web ajoute automatiquement l'en-tête "Last-Modified" aux pages statiques (par exemple. html,. css), basé sur la date de la dernière modification stockées dans le système de fichiers. Avec des pages dynamiques (p. ex. Php,. Aspx), ceci, bien sûr, ne peut pas être fait, et l'en-tête n'est pas envoyé.<br> + En particulier pour les pages qui sont générées dynamiquement, une petite recherche sur ce sujet est bénéfique. Il peut être quelque peu complexe, mais il permettra d'économiser beaucoup de demandes de page sur des pages qui ne devraient normalement pas être mis en cache.<br> + <br> + Plus d'informations:<br> + <br> + 1. <a class="external" href="http://fishbowl.pastiche.org/2002/10/21/http_conditional_get_for_rss_hackers" title="http://fishbowl.pastiche.org/2002/10/21/http_conditional_get_for_rss_hackers">HTTP Conditional Get for RSS Hackers</a><br> + 2. <a class="external" href="http://annevankesteren.nl/archives/2005/05/http-304" title="http://annevankesteren.nl/archives/2005/05/http-304">HTTP 304: Not Modified</a><br> + 3. <a class="external" href="http://www.cmlenz.net/blog/2005/05/on_http_lastmod.html" title="http://www.cmlenz.net/blog/2005/05/on_http_lastmod.html">On HTTP Last-Modified and ETag</a></p> + +<h3 id="Réduire_le_nombre_de_scripts_en_ligne">Réduire le nombre de scripts en ligne</h3> + +<p>Les scripts intégrés peut être coûteux pour le chargement de la page, puisque l'analyseur (ou parser) doit supposer qu'un script intégré pourrait modifier la structure de la page quand le "parsing" est en cours. Il est donc préférable, en général, de réduire l'utilisation des scripts intégrés et l'utilisation de document.write(), en particulier au contenu de sortie. Ces manipulations peuvent améliorer chargement globale de la page. Utilisez des méthodes modernes de W3C-DOM pour manipuler le contenu de la page pour les navigateurs modernes, plutôt que des approches plus fondées sur document.write ().</p> + +<h3 id="Utilisez_le_CSS_moderne_et_des_balises_valides">Utilisez le CSS moderne et des balises valides</h3> + +<p>L'utilisation de CSS modernes réduit la quantité de balisage, et peut réduire la nécessité de "spacer" les images, en termes de disposition, et peut très souvent remplacer des images de texte stylisé - qui "coutent" beaucoup plus que l'équivalent texte-et-CSS.<br> + Utiliser des balises valides a d'autres avantages. Tout d'abord, les navigateurs n'ont pas besoin d'effectuer de corrections d'erreurs lors de l'analyse du code HTML.<br> + En outre, la validité du balisage permet la libre utilisation d'autres outils qui peuvent pré-traiter vos pages web. Par exemple, <a class="external" href="http://tidy.sourceforge.net/" title="http://tidy.sourceforge.net/">HTML Tidy</a> peut supprimer des espaces blancs et des balises facultatives, mais il refusera de s'exécuter sur une page avec des erreurs de balisage graves.</p> + +<h3 id="Segmentez_votre_contenu">Segmentez votre contenu</h3> + +<p>Remplacer la mise en page basé sur des <table> par des blocs <div>, plutôt que des <table> très imbriquée comme dans l'exemple suivant:</p> + +<pre><TABLE> + <TABLE> + <TABLE> + ... + </TABLE> + </TABLE> +</TABLE> + +</pre> + +<p>Préferez des <table> non-imbriquées ou <div> comme dans l'exemple suivant:</p> + +<pre>> TABLE <TABLE> ...</ +> TABLE <TABLE> ...</ +> TABLE <TABLE> ...</</pre> + +<h3 id="Préciser_la_taille_des_images_et_des_tableaux">Préciser la taille des images et des tableaux</h3> + +<p>Si le navigateur peut immédiatement déterminer la hauteur et/ou la largeur de vos images et tableaux, il sera capable d'afficher une page web sans avoir à refondre le contenu. Cela n'augmente pas seulement la vitesse d'affichage de la page, mais aussi à empêcher les changements gênants dans la disposition d'une page lors du chargement. Pour cette raison, la hauteur et la largeur doit être spécifié pour les images, chaque fois que possible.<br> + Les tableaux doivent utiliser le sélecteur CSS selector:property combination:</p> + +<pre> table-layout: fixed; + +</pre> + +<p>et doit spécifier la largeur des colonnes en utilisant le COL et les balises html COLGROUP.</p> + +<h3 id="Choisissez_les_versions_des_navigateur_ciblés">Choisissez les versions des navigateur ciblés</h3> + +<p><br> + Pour atteindre les plus grandes améliorations dans la conception de la page, assurez-vous que des exigences raisonnables de l'agent utilisateur (user-agent) soit définies pour les projets. Cela ne nécessite pas que votre contenu apparaisse parfaitement sur tous les navigateurs, et surtout pas dans les navigateurs d'une version anterieure.<br> + <br> + Idéalement, vous devriez vous concentrez sur l'examen des navigateurs modernes qui prennent en charge des normes pertinentes. Il peut s'agir de: Firefox 5, Internet Explorer 9 sur Windows, Opera 11 sous Windows et Safari 5 sur Mac OS X.<br> + <br> + Notez, cependant, que beaucoup de conseils énumérés dans cette page sont des techniques de bon sens qui s'applique à tous, et peuvent être appliquées à n'importe quelle page web, indépendamment des exigences relatives des navigateurs.</p> + +<h3 id="Liens_connexes">Liens connexes</h3> + +<p><br> + * <a class="external" href="http://www.alsacreations.com/astuce/lire/527-optimisez-vos-pages-avec-yslow.html" title="http://www.alsacreations.com/astuce/lire/527-optimisez-vos-pages-avec-yslow.html">Optimisez vos pages avec Yslow</a><br> + * <a class="external" href="http://www.websiteoptimization.com/" title="http://www.websiteoptimization.com/">Livre: "Speed Up Your Site" par Andy King</a><br> + *<a class="external" href="http://webmonkey.wired.com/webmonkey/design/site_building/tutorials/tutorial2.html" title="http://webmonkey.wired.com/webmonkey/design/site_building/tutorials/tutorial2.html"> Site Optimization Tutorial </a>(WebMonkey) (en anglais) <br> + * <a class="external" href="http://developer.yahoo.com/performance/rules.html" title="http://developer.yahoo.com/performance/rules.html">Best Practices for Speeding Up Your Web Site</a> (en anglais) </p> + +<p> </p> + +<p><strong>Document d'information d'origine</strong><br> + <br> + * https://developer.mozilla.org/en/Tips_for_Authoring_Fast-loading_HTML_Pages</p> diff --git a/files/fr/web/guide/html/catégories_de_contenu/index.html b/files/fr/web/guide/html/catégories_de_contenu/index.html new file mode 100644 index 0000000000..35a8ed9779 --- /dev/null +++ b/files/fr/web/guide/html/catégories_de_contenu/index.html @@ -0,0 +1,175 @@ +--- +title: Catégories de contenu +slug: Web/Guide/HTML/Catégories_de_contenu +tags: + - Avancé + - Contenus + - Guide + - HTML +translation_of: Web/Guide/HTML/Content_categories +--- +<p>Chaque élément <a href="https://developer.mozilla.org/fr/docs/Web/HTML">HTML</a> est membre d'un certain nombre de catégories de contenu qui regroupent des éléments partageant un ensemble de caractéristiques. Ceci est un regroupement lâche, en ce sens qu'il ne crée pas réellement de relation entre les éléments de ces types, mais il aide à définir et à décrire leur comportement et les règles associées qu'ils doivent respecter, en particulier lorsque l'on entre dans leurs détails complexes. Il est également possible que les éléments ne soient membres d'aucune de ces catégories.</p> + +<p>Il y a trois types différents de catégories de contenu :</p> + +<ul> + <li>Les catégories de contenu principales qui décrivent un ensemble de règles de contenu partagées par une grande variété d'éléments ;</li> + <li>Les catégories de contenu relatives aux formulaires qui décrivent les règles de contenu partagées par les éléments en lien avec les formulaires ;</li> + <li>Les catégories de contenu spécifiques qui décrivent des catégories plus rares et qui s'appliquent à peu d'éléments, parfois dans un contexte particulier</li> +</ul> + +<div class="note"> +<p><strong>Note :</strong> un discours plus détaillé sur ces catégories de contenu et de leurs fonctionnalités comparatives dépasse le cadre de cet article ; pour en savoir plus, vous pouvez lire les <a href="https://html.spec.whatwg.org/multipage/dom.html#kinds-of-content">parties correspondantes de la spécification HTML</a> (en).</p> +</div> + +<div style="width: 50%;"><a href="/@api/deki/files/6244/=Content_categories_venn.png" title="Content_categories_venn.png"><img alt="Content_categories_venn.png" class="default internal" src="/@api/deki/files/6244/=Content_categories_venn.png?size=webview" style="height: 200px; width: 366px;"></a></div> + +<h2 id="Principales_catégories_de_contenu">Principales catégories de contenu</h2> + +<h3 id="Contenu_de_méta-données">Contenu de méta-données</h3> + +<p>Les éléments appartenant à cette catégorie modifient la présentation ou le comportement du reste du document, insèrent des liens vers d'autres documents ou comportent des informations sur la structure même des données.</p> + +<p>Les éléments appartenant à cette catégories sont : {{HTMLElement("base")}}, {{HTMLElement("command")}}{{ Obsolete_inline()}} , {{HTMLElement("link")}}, {{HTMLElement("meta")}}, {{HTMLElement("noscript")}}, {{HTMLElement("script")}}, {{HTMLElement("style")}} et {{HTMLElement("title")}}.</p> + +<h3 id="Contenu_de_flux">Contenu de flux</h3> + +<p>Les éléments appartenant à la catégorie de contenu de flux contiennent généralement du texte ou du contenu intégré. Ces éléments sont : {{HTMLElement("a")}}, {{HTMLElement("abbr")}}, {{HTMLElement("address")}}, {{HTMLElement("article")}}, {{HTMLElement("aside")}}, {{HTMLElement("audio")}}, {{HTMLElement("b")}},{{HTMLElement("bdo")}}, {{HTMLElement("bdi")}}, {{HTMLElement("blockquote")}}, {{HTMLElement("br")}}, {{HTMLElement("button")}}, {{HTMLElement("canvas")}}, {{HTMLElement("cite")}}, {{HTMLElement("code")}}, {{ Obsolete_inline() }}{{HTMLElement("command")}}, {{HTMLElement("data")}}, {{HTMLElement("datalist")}}, {{HTMLElement("del")}}, {{HTMLElement("details")}}, {{HTMLElement("dfn")}}, {{HTMLElement("div")}}, {{HTMLElement("dl")}}, {{HTMLElement("em")}}, {{HTMLElement("embed")}}, {{HTMLElement("fieldset")}}, {{HTMLElement("figure")}}, {{HTMLElement("footer")}}, {{HTMLElement("form")}}, {{HTMLElement("h1")}}, {{HTMLElement("h2")}}, {{HTMLElement("h3")}}, {{HTMLElement("h4")}}, {{HTMLElement("h5")}}, {{HTMLElement("h6")}}, {{HTMLElement("header")}}, {{HTMLElement("hgroup")}}, {{HTMLElement("hr")}}, {{HTMLElement("i")}}, {{HTMLElement("iframe")}}, {{HTMLElement("img")}}, {{HTMLElement("input")}}, {{HTMLElement("ins")}}, {{HTMLElement("kbd")}}, {{HTMLElement("keygen")}}{{deprecated_inline()}}, {{HTMLElement("label")}}, {{HTMLElement("main")}}, {{HTMLElement("map")}}, {{HTMLElement("mark")}}, {{MathMLElement("math")}}, {{HTMLElement("menu")}}, {{HTMLElement("meter")}}, {{HTMLElement("nav")}}, {{HTMLElement("noscript")}}, {{HTMLElement("object")}}, {{HTMLElement("ol")}}, {{HTMLElement("output")}}, {{HTMLElement("p")}}, {{HTMLElement("picture")}}, {{HTMLElement("pre")}}, {{HTMLElement("progress")}}, {{HTMLElement("q")}}, {{HTMLElement("ruby")}}, {{HTMLElement("s")}}, {{HTMLElement("samp")}}, {{HTMLElement("script")}}, {{HTMLElement("section")}}, {{HTMLElement("select")}}, {{HTMLElement("small")}}, {{HTMLElement("span")}}, {{HTMLElement("strong")}}, {{HTMLElement("sub")}}, {{HTMLElement("sup")}}, {{SVGElement("svg")}}, {{HTMLElement("table")}}, {{HTMLElement("template")}}, {{HTMLElement("textarea")}}, {{HTMLElement("time")}}, {{HTMLElement("ul")}}, {{HTMLElement("var")}}, {{HTMLElement("video")}}, {{HTMLElement("wbr")}} et le texte.</p> + +<p>Quelques autres éléments appartiennent à cette catégorie mais seulement sous certaines conditions :</p> + +<ul> + <li>{{HTMLElement("area")}} s'il est un descendant de l'élément {{HTMLElement("map")}}</li> + <li>{{HTMLElement("link")}} si l'attribut <a href="/fr/docs/HTML/Global_attributes#itemprop" title="/fr/docs/HTML/Global_attributes#itemprop"><strong>itemprop</strong></a> est présent</li> + <li>{{HTMLElement("meta")}} si l'attribut <a href="/fr/docs/HTML/Global_attributes#itemprop" title="/fr/docs/HTML/Global_attributes#itemprop"><strong>itemprop</strong></a> est présent</li> + <li>{{HTMLElement("style")}} si l'attribut {{htmlattrxref("scoped","style")}} {{deprecated_inline()}} est présent</li> +</ul> + +<h3 id="Contenu_sectionnant"><a id="contenu sectionnant" name="contenu sectionnant"></a>Contenu sectionnant</h3> + +<p>Les éléments appartenant à cette catégorie sont ceux créant une nouvelle <a href="/fr/docs/HTML/Sections_and_Outlines_of_an_HTML5_document" title="/fr/docs/HTML/Sections_and_Outlines_of_an_HTML5_document">section dans le plan du document</a> qui définit la portée des éléments {{HTMLElement("header")}}, des éléments {{HTMLElement("footer")}} et du <a href="#Contenu de titre" title="#Contenu de titre">contenu de titre</a>.</p> + +<p>Les éléments appartenant à cette catégorie sont les éléments {{HTMLElement("article")}}, {{HTMLElement("aside")}}, {{HTMLElement("nav")}} et {{HTMLElement("section")}}. </p> + +<div class="note"> +<p><em>Note :</em> Il ne faut pas confondre ce modèle de contenu avec la catégorie de <a href="/fr/docs/HTML/Sections_and_Outlines_of_an_HTML5_document#Racines_de_sectionnement" title="/fr/docs/HTML/Sections_and_Outlines_of_an_HTML5_document#Racines_de_sectionnement">racine de sectionnement</a> qui isole un contenu par rapport à la structure (ou plan) principale.</p> +</div> + +<h3 id="Contenu_de_titre"><a name="Contenu de titre">Contenu de titre</a></h3> + +<p>Le contenu de titre définit le titre d'une section, qu'elle soit marquée par un <a href="#">contenu sectionnant</a> de manière explicite ou qu'elle soit définie de manière implicite par le contenu de titre lui-même.</p> + +<p>Les éléments appartenant à cette catégorie sont {{HTMLElement("h1")}}, {{HTMLElement("h2")}}, {{HTMLElement("h3")}}, {{HTMLElement("h4")}}, {{HTMLElement("h5")}}, {{HTMLElement("h6")}} et {{HTMLElement("hgroup")}}.</p> + +<div class="note"> +<p><em>Note :</em> Bien qu'il soit probable qu'un élément {{HTMLElement("header")}} comporte du contenu de titre, il n'est pas lui-même un contenu de titre.</p> +</div> + +<div class="note"> +<p>Note : {{HTMLElement("hgroup")}} est supprimé du document recommandé par W3C.</p> +</div> + +<h3 id="Contenu_phrasé">Contenu phrasé</h3> + +<p>Le contenu phrasé définit le texte et le balisage qu'il contient. Des séquences de contenu phrasé constituent des paragraphes.</p> + +<p>Les éléments appartenant à cette catégorie sont {{HTMLElement("abbr")}}, {{HTMLElement("audio")}}, {{HTMLElement("b")}}, {{HTMLElement("bdo")}}, {{HTMLElement("br")}}, {{HTMLElement("button")}}, {{HTMLElement("canvas")}}, {{HTMLElement("cite")}}, {{HTMLElement("code")}}, {{ Obsolete_inline() }}{{HTMLElement("command")}}, {{HTMLElement("data")}}, {{HTMLElement("datalist")}}, {{HTMLElement("dfn")}}, {{HTMLElement("em")}}, {{HTMLElement("embed")}}, {{HTMLElement("i")}}, {{HTMLElement("iframe")}}, {{HTMLElement("img")}}, {{HTMLElement("input")}}, {{HTMLElement("kbd")}}, {{HTMLElement("keygen")}}{{deprecated_inline()}}, {{HTMLElement("label")}}, {{HTMLElement("mark")}}, {{MathMLElement("math")}}, {{HTMLElement("meter")}}, {{HTMLElement("noscript")}}, {{HTMLElement("object")}}, {{HTMLElement("output")}}, {{HTMLElement("picture")}}, {{HTMLElement("progress")}}, {{HTMLElement("q")}}, {{HTMLElement("ruby")}}, {{HTMLElement("samp")}}, {{HTMLElement("script")}}, {{HTMLElement("select")}}, {{HTMLElement("small")}}, {{HTMLElement("span")}}, {{HTMLElement("strong")}}, {{HTMLElement("sub")}}, {{HTMLElement("sup")}}, {{SVGElement("svg")}}, {{HTMLElement("textarea")}}, {{HTMLElement("time")}}, {{HTMLElement("var")}}, {{HTMLElement("video")}}, {{HTMLElement("wbr")}} et du texte brut (n'étant pas une simple suite de blancs).</p> + +<p>Quelques autres éléments appartiennent à cette catégorie mais seulement selon certaines conditions :</p> + +<ul> + <li>{{HTMLElement("a")}} s'il contient seulement du contenu phrasé</li> + <li>{{HTMLElement("area")}} s'il est un descendant de l'élément {{HTMLElement("map")}}</li> + <li>{{HTMLElement("del")}} s'il contient seulement du contenu phrasé</li> + <li>{{HTMLElement("ins")}} s'il contient seulement du contenu phrasé</li> + <li>{{HTMLElement("link")}} si l'attribut <a href="/fr/docs/HTML/Global_attributes#itemprop" title="/fr/docs/HTML/Global_attributes#itemprop"><strong>itemprop</strong></a> est présent</li> + <li>{{HTMLElement("map")}} s'il contient seulement du contenu phrasé</li> + <li>{{HTMLElement("meta")}} si l'attribut <a href="/fr/docs/HTML/Global_attributes#itemprop" title="/fr/docs/HTML/Global_attributes#itemprop"><strong>itemprop</strong></a> est présent</li> +</ul> + +<h3 id="Contenu_intégré">Contenu intégré</h3> + +<p>Le contenu intégré importe une autre ressource ou intègre du contenu provenant d'un autre langage de balisage ou d'un autre espace de noms dans le document. Les éléments appartenant à cette catégorie sont : {{HTMLElement("audio")}}, {{HTMLElement("canvas")}}, {{HTMLElement("embed")}}, {{HTMLElement("iframe")}}, {{HTMLElement("img")}}, {{MathMLElement("math")}}, {{HTMLElement("object")}}, {{HTMLElement("svg")}}, {{HTMLElement("video")}}.</p> + +<h3 id="Contenu_interactif">Contenu interactif</h3> + +<p>Le contenu interactif regroupe des éléments spécialement conçus pour une interaction avec l'utilisateur. Les éléments appartenant à cette catégories sont : {{HTMLElement("a")}}, {{HTMLElement("button")}}, {{HTMLElement("details")}}, {{HTMLElement("embed")}}, {{HTMLElement("iframe")}}, {{HTMLElement("keygen")}}{{deprecated_inline()}} , {{HTMLElement("label")}}, {{HTMLElement("select")}}, et {{HTMLElement("textarea")}}.</p> + +<p>Quelques éléments appartiennent à cette catégorie seulement sous certaines conditions :</p> + +<ul> + <li>{{HTMLElement("audio")}} si l'attribut {{htmlattrxref("controls", "audio")}} est présent</li> + <li>{{HTMLElement("img")}} si l'attribut {{htmlattrxref("usemap", "img")}} est présent</li> + <li>{{HTMLElement("input")}} si l'attribubt {{htmlattrxref("type", "input")}} ne vaut pas <code>hidden</code></li> + <li>{{HTMLElement("menu")}} si l'attribut {{htmlattrxref("type", "menu")}} vaut <code>toolbar</code></li> + <li>{{HTMLElement("object")}} si l'attribut {{htmlattrxref("usemap", "object")}} est présent</li> + <li>{{HTMLElement("video")}}, si l'attribut {{htmlattrxref("controls", "video")}} est présent</li> +</ul> + +<h3 id="Contenu_tangible">Contenu tangible</h3> + +<p>Un contenu peut être dit tangible lorsqu'il n'est ni vide ni caché. Les éléments dont le modèle de contenu est de flux ou phrasé devraient toujours avoir au moins un noeud dont le contenu est tangible.</p> + +<h3 id="Contenu_associé_aux_formulaires">Contenu associé aux formulaires</h3> + +<p>Le contenu associé aux formulaires contient les éléments possédés par un formulaire, exposé avec un attribut <strong>form</strong>. Être possédé par un formulaire signifie être descendant d'un élément {{HTMLElement("form")}} ou de l'élément dont l'identifiant est référencé par la valeur de l'attribut <strong>form</strong>.</p> + +<p>Cette catégorie contient les éléments :</p> + +<ul> + <li>{{HTMLElement("button")}}</li> + <li>{{HTMLElement("fieldset")}}</li> + <li>{{HTMLElement("input")}}</li> + <li>{{HTMLElement("keygen")}}{{deprecated_inline()}}</li> + <li>{{HTMLElement("label")}}</li> + <li>{{HTMLElement("meter")}}</li> + <li>{{HTMLElement("object")}}</li> + <li>{{HTMLElement("output")}}</li> + <li>{{HTMLElement("progress")}}</li> + <li>{{HTMLElement("select")}}</li> + <li>{{HTMLElement("textarea")}}</li> +</ul> + +<p> Cette catégorie peut être subdivisée en plusieurs sous-catégories.</p> + +<dl> + <dt><a name="Form_listed">listed</a> (éléments listés)</dt> + <dd>Les éléments étant listés sont les ensembles IDL <a href="/fr/docs/DOM/form.elements" title="DOM/form.elements">form.elements</a> et fieldset.elements. Ce sont : {{HTMLElement("button")}}, {{HTMLElement("fieldset")}}, {{HTMLElement("input")}}, {{HTMLElement("keygen")}}{{deprecated_inline()}} , {{HTMLElement("object")}}, {{HTMLElement("output")}}, {{HTMLElement("select")}}, et {{HTMLElement("textarea")}}.</dd> + <dt><a name="Form_labelable">labelable</a> (éléments étiquetables)</dt> + <dd>Les éléments pouvant être associés avec des éléments {{HTMLElement("label")}}. Ce sont : {{HTMLElement("button")}}, {{HTMLElement("input")}}, {{HTMLElement("keygen")}}{{deprecated_inline()}} , {{HTMLElement("meter")}}, {{HTMLElement("output")}}, {{HTMLElement("progress")}}, {{HTMLElement("select")}} et {{HTMLElement("textarea")}}.</dd> + <dt><a name="Form_submittable">submittable</a> (éléments participants à l'envoi du formulaire)</dt> + <dd>Les éléments pouvant être utilisés pour construire les données du formulaires quand celui-ci est envoyé. Ce sont : {{HTMLElement("button")}}, {{HTMLElement("input")}}, {{HTMLElement("keygen")}}{{deprecated_inline()}} , {{HTMLElement("object")}}, {{HTMLElement("select")}} et {{HTMLElement("textarea")}}.</dd> + <dt><a name="Form_resettable">resettable</a> (éléments de ré-initialisation)</dt> + <dd>Éléments pouvant être impactés lorsqu'un formulaire est ré-initialisé. Ce sont : {{HTMLElement("input")}}, {{HTMLElement("keygen")}}{{deprecated_inline()}}, {{HTMLElement("output")}},{{HTMLElement("select")}} et {{HTMLElement("textarea")}}.</dd> +</dl> + +<h2 id="Catégories_secondaires">Catégories secondaires</h2> + +<p>Il existe des classifications secondaires d'éléments qu'il peut être utile de connaître également.</p> + +<h3 id="Éléments_supports_de_script">Éléments supports de script</h3> + +<p>Les éléments supports de script sont des éléments qui ne contribuent pas directement à la sortie rendue d'un document. Au lieu de cela, ils servent à prendre en charge les scripts, soit en contenant ou en spécifiant le code de script directement, soit en spécifiant les données qui seront utilisées par les scripts. Ce sont :</p> + +<ul> + <li>{{HTMLElement("script")}}</li> + <li>{{HTMLElement("template")}}</li> +</ul> + +<h2 id="Modèle_de_contenu_transparent">Modèle de contenu transparent</h2> + +<p>Si l'élément possède un modèle de contenu transparent, son contenu doit alors être structuré comme du HTML5 valide, et ce, même si l'élément transparent a été enlevé et remplacé par ses éléments fils.</p> + +<p>Les éléments {{HTMLElement("del")}} et {{HTMLELement("ins")}} sont des exemples d'éléments transparents.</p> + +<pre><p>Bonjour <del><em>tout</em></del> <ins>le monde</ins>.</p> +</pre> + +<p>Si ces éléments étaient retirés, ce fragment de code HTML serait toujours du HTML valide.</p> + +<pre><p>Bonjour <em>tout</em> le monde.</p> +</pre> + +<h2 id="Autres_modèles_de_contenu">Autres modèles de contenu</h2> + +<p><a href="/fr/docs/HTML/Sections_and_Outlines_of_an_HTML5_document#Racines_de_sectionnement" title="/fr/docs/HTML/Sections_and_Outlines_of_an_HTML5_document#Racines_de_sectionnement">Racine de sectionnement.</a></p> diff --git a/files/fr/web/guide/html/formulaires/advanced_styling_for_html_forms/index.html b/files/fr/web/guide/html/formulaires/advanced_styling_for_html_forms/index.html new file mode 100644 index 0000000000..6d6a68bd4c --- /dev/null +++ b/files/fr/web/guide/html/formulaires/advanced_styling_for_html_forms/index.html @@ -0,0 +1,469 @@ +--- +title: Composition avancée des formulaires HTML +slug: Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms +tags: + - Avancé + - CSS + - Exemple + - Formulaires + - Guide + - HTML + - Web +translation_of: Learn/Forms/Advanced_form_styling +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML", "Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets", "Web/Guide/HTML/Formulaires")}}</div> + +<p class="summary">Dans cet article, nous verrons comment utiliser les <a href="/fr/docs/Apprendre/CSS">CSS</a> avec les formulaires <a href="/fr/docs/Glossaire/HTML">HTML</a> pour modifier le style de certains widgets difficiles à personnaliser. Comme nous l'avons vu dans l'<a href="/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">article précédent</a>, les champs texte et les boutons sont parfaitement compatibles avec les CSS. Maintenant, nous allons approfondir la part sombre de la composition stylistique des formulaires HTML.</p> + +<p>Avant d'aller plus loin, faisons un rappel pour deux types de widgets de formulaires :</p> + +<dl> + <dt>la brute</dt> + <dd>Éléments, dont le style n'est que difficilement modifiable, demandant des astuces complexes, nécessitant parfois de faire appel à une connaissance avancée des CSS3.</dd> + <dt>le truand</dt> + <dd>Oubliez l'emploi des CSS pour modifier le style de ces éléments. Au mieux, vous pourrez faire des petites choses, mais elle ne seront pas reproductibles sur d'autres navigateurs ; il ne sera jamais possible de prendre un contrôle total de leur apparence.</dd> +</dl> + +<h2 id="Possibilités_d'expression_avec_les_CSS">Possibilités d'expression avec les CSS</h2> + +<p>Le problème fondamental avec les widgets de formulaire, autres que champs de texte et boutons, est que dans de nombreux cas, le CSS ne possède pas assez d'expressions pour styliser correctement les widgets complexes.</p> + +<p>L'évolution récente du HTML et des CSS a étendu l'expressivité des CSS :</p> + +<ul> + <li><a href="http://www.w3.org/TR/CSS21/selector.html#dynamic-pseudo-classes" rel="external" title="http://www.w3.org/TR/CSS21/selector.html#dynamic-pseudo-classes">CSS 2.1</a> était très limité et n'offrait que trois pseudo-classes : + + <ul> + <li>{{cssxref(":active")}}</li> + <li>{{cssxref(":focus")}}</li> + <li>{{cssxref(":hover")}}</li> + </ul> + </li> + <li><a href="http://www.w3.org/TR/css3-selectors/" rel="external" title="http://www.w3.org/TR/css3-selectors/">CSS Selector Level 3</a> a ajouté quelques nouvelles pseudo-classes relatives aux formulaires HTML : + <ul> + <li>{{cssxref(":enabled")}}</li> + <li>{{cssxref(":disabled")}}</li> + <li>{{cssxref(":checked")}}</li> + <li>{{cssxref(":indeterminate")}}</li> + </ul> + </li> + <li><a href="http://dev.w3.org/csswg/css3-ui/#pseudo-classes" rel="external" title="http://dev.w3.org/csswg/css3-ui/#pseudo-classes">CSS Basic UI Level 3</a> a ajouté quelques autres pseudo-classes pour décrire l'état du widget : + <ul> + <li>{{cssxref(":default")}}</li> + <li>{{cssxref(":valid")}}</li> + <li>{{cssxref(":invalid")}}</li> + <li>{{cssxref(":in-range")}}</li> + <li>{{cssxref(":out-of-range")}}</li> + <li>{{cssxref(":required")}}</li> + <li>{{cssxref(":optional")}}</li> + <li>{{cssxref(":read-only")}}</li> + <li>{{cssxref(":read-write")}}</li> + </ul> + </li> + <li><a href="http://dev.w3.org/csswg/selectors4/" rel="external" title="http://dev.w3.org/csswg/selectors4/">CSS Selector Level 4</a> actuellement en développement actif et objet de grandes discussions ne prévoit pas d'ajouter grand‑chose pour améliorer les formulaires : + <ul> + <li>{{cssxref(":user-error")}} qui est juste une amélioration de la pseudo‑classe {{cssxref(":invalid")}}.</li> + </ul> + </li> +</ul> + +<p>Voilà un bon début, mais il y a deux problèmes. Primo, certains navigateurs ne mettent pas en œuvre des fonctionnalités au-delà de CSS 2.1. Secundo, ils ne sont tout simplement pas assez perfectionnés pour styliser des widgets complexes, comme les sélecteurs de date.</p> + +<p>Il y a quelques expérimentations par les fournisseurs de navigateurs pour étendre l'expressivité des CSS sur les formulaires ; dans certains cas, il est bon de savoir ce qui est disponible..</p> + +<div class="warning"> +<p><strong>Avertissement :</strong> Même si ces expérimentations sont intéressantes, <strong>elles ne sont pas normées, ce qui signifie qu'elles ne sont pas fiables</strong>. Si vous les utilisez (et vous ne devriez probablement pas le faire souvent), vous le faites à vos propres risques et périls ; <a href="http://www.alistapart.com/articles/every-time-you-call-a-proprietary-feature-css3-a-kitten-dies/">vous faites quelque chose qui peut être mauvais pour le Web</a> en utilisant des propriétés non standard.</p> +</div> + +<ul> + <li><a href="/fr/docs/CSS/CSS_Reference/Mozilla_Extensions" title="/en-US/docs/CSS/CSS_Reference/Mozilla_Extensions">Extensions des CSS Mozilla </a> + + <ul> + <li>{{cssxref(":-moz-placeholder")}}</li> + <li>{{cssxref(":-moz-submit-invalid")}}</li> + <li>{{cssxref(":-moz-ui-invalid")}}</li> + <li>{{cssxref(":-moz-ui-valid")}}</li> + </ul> + </li> + <li><a href="/fr/docs/CSS/CSS_Reference/Webkit_Extensions" title="/en-US/docs/CSS/CSS_Reference/Webkit_Extensions">Extensions des CSS WebKit </a> + <ul> + <li>{{cssxref("::-webkit-input-placeholder")}}</li> + <li><a href="http://trac.webkit.org/wiki/Styling%20Form%20Controls" rel="external" title="http://trac.webkit.org/wiki/Styling Form Controls">et beaucoup d'autres</a></li> + </ul> + </li> + <li><a href="http://msdn.microsoft.com/en-us/library/ie/hh869403%28v=vs.85%29.aspx" rel="external" title="http://msdn.microsoft.com/en-us/library/ie/hh869403%28v=vs.85%29.aspx">Extensions des CSS Microsoft</a> + <ul> + <li><code><a href="http://msdn.microsoft.com/en-us/library/ie/hh772745%28v=vs.85%29.aspx" rel="external" title="http://msdn.microsoft.com/en-us/library/ie/hh772745%28v=vs.85%29.aspx">:-ms-input-placeholder</a></code></li> + </ul> + </li> +</ul> + +<h3 id="Contrôle_de_l'apparence_des_éléments_de_formulaire">Contrôle de l'apparence des éléments de formulaire</h3> + +<p>Les navigateurs fondés sur WebKit- (Chrome, Safari) et Gecko- (Firefox) offrent les meilleures possibilités de personnalisation des widgets HTML. Ils sont aussi disponibles sur plateforme croisées, et donc ils nécessitent un mécanisme de bascule entre les widgets de « look and feel » natif et widget stylistiquement composables par l'utilisateur.</p> + +<p>À cette fin, ils utilisent une propriété propriétaire : {{cssxref("-webkit-appearance")}} ou {{cssxref("-moz-appearance")}}. <strong>Ces propriétés ne sont pas normées et ne doivent pas être utilisées</strong>. En fait, elles se comportent même différemment entre WebKit et Gecko. Cependant, il y a une valeur qu'il est bon de connaître : <code>none</code>. Avec cette valeur, vous êtes en mesure d'obtenir un contrôle (presque total) sur le style des widgets donnés.</p> + +<p>Donc, si vous avez du mal à appliquer un style à un élément, essayez d'utiliser ces propriétés propriétaires. Nous verrons quelques exemples ci-dessous, mais le cas d'utilisation le plus connu de cette propriété est relatif au style des champs de recherche sur les navigateurs WebKit :</p> + +<pre class="brush: css"><style> +input[type=search] { + border: 1px dotted #999; + border-radius: 0; + + -webkit-appearance: none; +} +</style> + +<form> + <input type="search"> +</form></pre> + +<p>{{EmbedLiveSample("Contrôle_de_l'apparence_des_éléments_de_formulaire", 250, 40)}}</p> + +<div class="note"> +<p><strong>Note :</strong> Il est toujours difficile de prédire l'avenir, quand on parle de techniques Web. L'extension des possibilités d'expression des CSS est difficile ; il y a un travail exploratoire avec d'autres spécifications, telles que <a href="http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html" rel="external" title="http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html">Shadow DOM</a> qui offrent certaines perspectives. La quête du formulaire de style totalement composable est loin d'être terminée.</p> +</div> + +<h2 id="Exemples">Exemples</h2> + +<h3 id="Cases_à_cocher_et_boutons_radio">Cases à cocher et boutons radio</h3> + +<p>Composer le style d'une case à cocher ou d'un bouton radio conduit à un certain désordre en soi. Par exemple, la taille des cases à cocher et des boutons radio n'est pas vraiment destinée à être modifiée et les navigateurs peuvent réagir très différemment, si vous essayez de le faire.</p> + +<h4 id="Une_simple_case_à_cocher">Une simple case à cocher</h4> + +<p>Considérons la case à cocher suivante :</p> + +<pre class="brush: html"><span><input type="checkbox"></span></pre> + +<pre class="brush: css">span { + display: inline-block; + background: red; +} + +input[type=checkbox] { + width : 100px; + height: 100px; +}</pre> + +<p>Voici les différentes façons dont divers navigateurs gèrent cela :</p> + +<table> + <thead> + <tr> + <th scope="col">Navigateur</th> + <th scope="col">Rendu</th> + </tr> + </thead> + <tbody> + <tr> + <td>Firefox 57 (Mac OSX)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15671/firefox-mac-checkbox.png" style="height: 118px; width: 120px;"></td> + </tr> + <tr> + <td>Firefox 57 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15691/firefox-windows-checkbox.png" style="height: 115px; width: 113px;"></td> + </tr> + <tr> + <td>Chrome 63 (Mac OSX)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15676/chrome-mac-checkbox.png" style="height: 117px; width: 116px;"></td> + </tr> + <tr> + <td>Chrome 63 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15681/chrome-windows-checkbox.png" style="height: 117px; width: 120px;"></td> + </tr> + <tr> + <td>Opera 49 (Mac OSX)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15701/opera-mac-checkbox.png" style="height: 119px; width: 118px;"></td> + </tr> + <tr> + <td>Internet Explorer 11 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15696/ie11-checkbox.png" style="height: 112px; width: 119px;"></td> + </tr> + <tr> + <td>Edge 16 (Windows 10)</td> + <td><img alt="" src="https://mdn.mozillademos.org/files/15686/edge-checkbox.png" style="height: 118px; width: 119px;"></td> + </tr> + </tbody> +</table> + +<h4 id="Un_exemple_un_peu_plus_compliqué">Un exemple un peu plus compliqué</h4> + +<p>Comme Opera et Internet Explorer n'ont pas de fonctionnalités telles que {{cssxref("-webkit-appearance")}} ou {{cssxref("-moz-appearance")}}, leur utilisation n'est pas appropriée. Heureusement, nous sommes dans un cas où les CSS disposent d'assez d'expressions pour trouver des solutions. Prenons un exemple courant :</p> + +<pre class="brush: html"><form> + <fieldset> + <p> + <input type="checkbox" id="first" name="fruit-1" value="cerise"> + <label for="first">J'aime les cerises</label> + </p> + <p> + <input type="checkbox" id="second" name="fruit-2" value="banane" disabled> + <label for="second">Je ne peux pas aimer la banane</label> + </p> + <p> + <input type="checkbox" id="third" name="fruit-3" value="fraise"> + <label for="third">J'aime les fraises</label> + </p> + </fieldset> +</form></pre> + +<p>avec une composition stylistique élémentaire :</p> + +<pre class="brush: css">body { + font: 1em sans-serif; +} + +form { + display: inline-block; + + padding: 0; + margin : 0; +} + +fieldset { + border : 1px solid #CCC; + border-radius: 5px; + margin : 0; + padding: 1em; +} + +label { + cursor : pointer; +} + +p { + margin : 0; +} + +p+p { + margin : .5em 0 0; +}</pre> + +<p>Maintenant composons pour avoir une case à cocher personnalisée.</p> + +<p>Le plan consiste à remplacer la case à cocher native par une image de notre choix. Tout d'abord, nous devons préparer une image avec tous les états requis pour une case à cocher. Ces états sont : non coché, coché, non coché désactivé et coché désactivé. Cette image sera utilisée comme fantôme des CSS :</p> + +<p><img alt="Check box CSS Sprite" src="/files/4173/checkbox-sprite.png" style="height: 64px; width: 16px;"></p> + +<p>Commençons par masquer les cases à cocher d'origine. Nous les déplacerons simplement à l'extérieur de la fenêtre de visualisation de la page. Il y a deux choses importantes à considérer ici :</p> + +<ul> + <li>N'utilisez pas <code>display:none</code> pour masquer la case à cocher, car comme nous le verrons ci-dessous, nous avons besoin que la case à cocher soit disponible pour l'utilisateur. Avec <code>display:none</code>, la case à cocher n'est plus accessible à l'utilisateur, ce qui signifie qu'il est impossible de la cocher ou de la décocher.</li> + <li>Nous utiliserons quelques sélecteurs CSS3 pour réaliser notre style. Afin de prendre en charge les navigateurs existants, nous pouvons préfixer tous nos sélecteurs avec la pseudo-classe {{cssxref(":root")}}. Dans l'état actuel des implémentations, tous les navigateurs prenant en charge ce dont nous avons besoin prenent en charge également la pseudo-classe {{cssxref(":root")}}, mais d'autres ne le font pas. Ceci est un exemple de moyen pratique pour filtrer l'ancien Internet Explorer. Ces anciens navigateurs verront la case à cocher normale tandis que les navigateurs modernes verront la case à cocher personnalisée.</li> +</ul> + +<pre class="brush: css">:root input[type=checkbox] { + /* les cases à cocher d'origine sont placées en dehors de la vue */ + position: absolute; + left: -1000em; +}</pre> + +<p>Maintenant que nous sommes débarrassés des cases à cocher natives, ajoutons la nôtre. Pour cela, nous utiliserons le pseudo élément {{cssxref(":before")}} de l'élément {{HTMLElement("label")}} qui suit la case à cocher originale. Ainsi, dans le sélecteur suivant, nous utilisons le sélecteur d'attributs pour cibler la case à cocher, puis nous utilisons le sélecteur de parents adjacent pour cibler le <code>label</code> suivant la case à cocher originale. Enfin, nous accédons au pseudo-élément {{cssxref(":before")}} et le styliser pour qu'il affiche notre case à cocher personnalisée non cochée.</p> + +<pre class="brush: css">:root input[type=checkbox] + label:before { + content: ""; + display: inline-block; + width : 16px; + height : 16px; + margin : 0 .5em 0 0; + background: url("https://developer.mozilla.org/files/4173/checkbox-sprite.png") no-repeat 0 0; + +/* Ce qui suit est utilisé pour ajuster la position des cases à cocher + sur la ligne de base suivante */ + + vertical-align: bottom; + position: relative; + bottom: 2px; +}</pre> + +<p>Nous utilisons les pseudo-classes {{cssxref(":checked")}} et {{cssxref(":disabled")}} sur la case à cocher d'origine pour changer l'état de notre case à cocher personnalisée en conséquence. Comme nous utilisons un fantôme des CSS, tout ce que nous avons à faire est de changer la position de l'arrière-plan.</p> + +<pre class="brush: css">:root input[type=checkbox]:checked + label:before { + background-position: 0 -16px; +} + +:root input[type=checkbox]:disabled + label:before { + background-position: 0 -32px; +} + +:root input[type=checkbox]:checked:disabled + label:before { + background-position: 0 -48px; +}</pre> + +<p>Une dernière chose (mais très importante) : lorsqu'un utilisateur utilise le clavier pour naviguer d'un widget à un autre, chaque widget qui reçoit le focus doit être marqué visuellement. Comme nous cachons les cases à cocher natives, nous devons implémenter cette fonctionnalité nous-mêmes : l'utilisateur doit pouvoir voir où elles se trouvent dans le formulaire. Le CSS suivant met en œuvre le focus sur les cases à cocher personnalisées.</p> + +<pre class="brush: css">:root input[type=checkbox]:focus + label:before { + outline: 1px dotted black; +}</pre> + +<p>Voyez directement ici le résultat :</p> + +<p>{{EmbedLiveSample("Un_exemple_un_peu_plus_compliqué", 250, 130)}}</p> + +<h3 id="Gérer_le_cauchemar_<select>">Gérer le cauchemar <select></h3> + +<p>L'élément {{HTMLElement("select")}} est considéré comme un widget « truand », car il est impossible de lui composer un style cohérent entre les plateformes. Toutefois, certaines choses restent possibles. Plutôt qu'une longue explication, voyons un exemple :</p> + +<pre class="brush: html"><select> + <option>Cerise</option> + <option>Banane</option> + <option>Fraise</option> +</select></pre> + +<pre class="brush: css">select { + width : 80px; + padding : 10px; +} + +option { + padding : 5px; + color : red; +}</pre> + +<p>Le tableau suivant montre comment divers navigateurs gèrent cela, dans deux cas. Les deux premières colonnes ne sont que l'exemple ci-dessus. Les deux colonnes suivantes utilisent des CSS personnalisés supplémentaires, pour avoir plus de contrôle sur l'apparence du widget :</p> + +<pre class="brush: css">select, option { + -webkit-appearance : none; /* Pour avoir le contrôle de l'apparence sur WebKit/Chromium */ + -moz-appearance : none; /* Pour avoir le contrôle sur l'apparence sur Gecko */ + + /* Pour avoir le contrôle sur l'apparence et sur Trident (IE) + Notez que cela fonctionne aussi sur Gecko et a des effets limités sur WebKit */ + background : none; +}</pre> + +<table class="standard-table"> + <thead> + <tr> + <th colspan="1" rowspan="2" scope="col">Navigateur</th> + <th colspan="2" scope="col" style="text-align: center;">Rendu classique</th> + <th colspan="2" scope="col" style="text-align: center;">Rendu travaillé</th> + </tr> + <tr> + <th scope="col" style="text-align: center;">fermé</th> + <th scope="col" style="text-align: center;">ouvert</th> + <th scope="col" style="text-align: center;">fermé</th> + <th scope="col" style="text-align: center;">ouvert</th> + </tr> + </thead> + <tbody> + <tr> + <td>Firefox 57 (Mac OSX)</td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15672/firefox-mac-select-1-closed.png" style="height: 55px; width: 91px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15673/firefox-mac-select-1-open.png" style="height: 76px; width: 119px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15674/firefox-mac-select-2-closed.png" style="height: 67px; width: 94px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15675/firefox-mac-select-2-open.png" style="height: 82px; width: 116px;"></td> + </tr> + <tr> + <td>Firefox 57 (Windows 10)</td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15692/firefox-windows-select-1-closed.png" style="height: 65px; width: 92px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15693/firefox-windows-select-1-open.png" style="height: 129px; width: 103px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15694/firefox-windows-select-2-closed.png" style="height: 69px; width: 92px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15695/firefox-windows-select-2-open.png" style="height: 144px; width: 108px;"></td> + </tr> + <tr> + <td>Chrome 63 (Mac OSX)</td> + <td style="vertical-align: top; text-align: center;"><img alt="" src="https://mdn.mozillademos.org/files/15677/chrome-mac-select-1-closed.png" style="height: 36px; width: 92px;"></td> + <td style="vertical-align: top; text-align: center;"><img alt="" src="https://mdn.mozillademos.org/files/15678/chrome-mac-select-1-open.png" style="height: 62px; width: 108px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15684/chrome-windows-select-2-closed.png" style="height: 53px; width: 92px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15680/chrome-mac-select-2-open.png" style="height: 75px; width: 110px;"></td> + </tr> + <tr> + <td>Chrome 63 (Windows 10)</td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15682/chrome-windows-select-1-closed.png" style="height: 50px; width: 91px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15683/chrome-windows-select-1-open.png" style="height: 95px; width: 91px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15684/chrome-windows-select-2-closed.png" style="height: 53px; width: 92px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15685/chrome-windows-select-2-open.png" style="height: 104px; width: 93px;"></td> + </tr> + <tr> + <td>Opera 49 (Mac OSX)</td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15702/opera-mac-select-1-closed.png" style="height: 33px; width: 92px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15703/opera-mac-select-1-open.png" style="height: 67px; width: 115px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15704/opera-mac-select-2-closed.png" style="height: 49px; width: 89px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15705/opera-mac-select-2-open.png" style="height: 77px; width: 115px;"></td> + </tr> + <tr> + <td>IE11 (Windows 10)</td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15697/ie11-select-1-closed.png" style="height: 52px; width: 91px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15698/ie11-select-1-open.png" style="height: 84px; width: 120px;"></td> + <td style="text-align: center; vertical-align: middle;"><img alt="" src="https://mdn.mozillademos.org/files/15699/ie11-select-2-closed.png" style="height: 57px; width: 93px;"></td> + <td style="text-align: center; vertical-align: middle;"><img alt="" src="https://mdn.mozillademos.org/files/15700/ie11-select-2-open.png" style="height: 89px; width: 123px;"></td> + </tr> + <tr> + <td>Edge 16 (Windows 10)</td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15687/edge-select-1-closed.png" style="height: 52px; width: 91px;"></td> + <td style="text-align: center; vertical-align: top;"><img alt="" src="https://mdn.mozillademos.org/files/15688/edge-select-1-open.png" style="height: 84px; width: 105px;"></td> + <td style="text-align: center; vertical-align: middle;"><img alt="" src="https://mdn.mozillademos.org/files/15689/edge-select-2-closed.png" style="height: 51px; width: 89px;"></td> + <td style="text-align: center; vertical-align: middle;"><img alt="" src="https://mdn.mozillademos.org/files/15690/edge-select-2-open.png" style="height: 83px; width: 93px;"></td> + </tr> + </tbody> +</table> + +<p>Comme vous pouvez le voir, malgré l'aide des propriétés <code>-*-appearance</code>, il reste quelques problèmes :</p> + +<ul> + <li>La propriété {{cssxref("padding")}} est gérée de manière incohérente entre les divers systèmes d'exploitation et navigateurs.</li> + <li>Internet Explorer ancien ne permet pas un style sans à-coups.</li> + <li>Firefox ne dispose d'aucun moyen pour rendre la flèche de déroulement.</li> + <li>Si vous voulez donner un style aux éléments {{HTMLElement("option")}} dans la liste déroulante, le comportement de Chrome et Opera varie d'un système à l'autre.</li> +</ul> + +<p>De plus, avec notre exemple, nous n'utilisons que trois propriétés CSS. Imaginez le désordre quand on considère encore plus de propriétés CSS. Comme vous pouvez le voir, les CSS ne sont pas adaptées pour changer l'apparence et la convivialité de ces widgets de manière cohérente, mais elles vous permettent quand même d'ajuster certaines choses. Pour autant que vous soyez prêt à vivre avec des différences d'un navigateur et d'un système d'exploitation à l'autre.</p> + +<p>Nous vous aiderons à comprendre quelles sont les propriétés qui conviennent dans l'article suivant : <a href="/fr/docs/Properties_compatibility_table_for_forms_widgets" title="/en-US/docs/Properties_compatibility_table_for_forms_widgets">Tableau de compatibilité des propriétés entre les widgets de formulaire</a>.</p> + +<h2 id="Vers_des_formulaires_plus_sympas_bibliothèques_utiles_et_«_polyfill_»_(prothèses_d'émulation)">Vers des formulaires plus sympas : bibliothèques utiles et<strong> </strong>« <strong>polyfill » (prothèses d'émulation)</strong></h2> + +<p>Bien que les CSS soient assez expressives pour les cases à cocher et les boutons radio, c'est loin d'être vrai pour les widgets plus avancés. Même si certaines choses sont possibles avec l'élément {{HTMLElement("select")}}, le widget <code>file</code> ne peut pas être stylisé du tout. Il en est de même pour le sélecteur de date, etc.</p> + +<p>Si vous souhaitez avoir un contrôle total sur les widgets de formulaire, vous n'avez pas d'autre choix que de compter sur JavaScript. Dans l'article<a href="/fr/docs/HTML/Forms/How_to_build_custom_form_widgets"> Comment créer des widgets de formulaires personnalisés</a>, nous voyons comment le faire nous-mêmes, mais il existe des bibliothèques très utiles pouvant vous aider :</p> + +<ul> + <li><a href="http://sprawsm.com/uni-form/" rel="external" title="http://sprawsm.com/uni-form/">Uni-form</a> est un canevas de standardisation du balisage des formulaires, en le composant stylistiquement avec des CSS. Il offre également quelques fonctionnalités supplémentaires lorsqu'il est utilisé avec jQuery, mais c'est optionnel.</li> + <li><a href="http://formalize.me/" rel="external" title="http://formalize.me/">Formalize</a> est une extension des canevas JavaScript courants (tels que jQuery, Dojo, YUI, etc.) aidant à rationaliser et personnaliser les formulaires.</li> + <li><a href="http://www.emblematiq.com/lab/niceforms/" rel="external" title="http://www.emblematiq.com/lab/niceforms/">Niceforms</a> est une méthode JavaScript autonome fournissant une personnalisation complète des formulaires Web. Vous pouvez utiliser certains thèmes intégrés ou créer les vôtres.</li> +</ul> + +<p>Les bibliothèques suivantes ne visent pas seulement les formulaires, mais elles ont des fonctionnalités très intéressantes pour les traiter :</p> + +<ul> + <li><a href="http://jqueryui.com/" rel="external" title="http://jqueryui.com/">jQuery UI</a> offre des widgets avancés et personnalisables très intéressants, comme les sélecteurs de date (avec une attention particulière pour l'accessibilité).</li> + <li><a href="http://twitter.github.com/bootstrap/base-css.html#forms" rel="external" title="http://twitter.github.com/bootstrap/base-css.html#forms">Twitter Bootstrap</a> peut être très utile si vous voulez normaliser vos formulaires.</li> + <li><a href="https://afarkas.github.io/webshim/demos/" rel="external" title="http://afarkas.github.com/webshim/demos/demos/webforms.html">WebShim</a> est un énorme outil pouvant vous aider à gérer la prise en charge des navigateurs HTML5. La partie formulaires Web peut être très utile.</li> +</ul> + +<p>Rappelez-vous que lier CSS et JavaScript peut avoir des effets collatéraux. Donc, si vous choisissez d'utiliser l'une de ces bibliothèques, vous devez toujours prévoir des solutions de repli dans les feuilles de style en cas d'échec du script. Il y a de nombreuses raisons pour lesquelles les scripts peuvent échouer, surtout dans le monde des mobiles et vous devez concevoir votre site Web ou votre application pour traiter ces cas le mieux possible.</p> + +<h2 id="Conclusion">Conclusion</h2> + +<p> </p> + +<p>Bien qu'il y ait encore des points noirs avec l'utilisation des CSS dans les formulaires HTML, il y a souvent moyen de les contourner. Il n'existe pas de solution générale et nette, mais les navigateurs modernes offrent de nouvelles possibilités. Pour l'instant, la meilleure solution est d'en savoir plus sur la façon dont les divers navigateurs prennent en charge les CSS, telles qu'appliquées aux widgets de formulaires HTML.</p> + +<p>Dans le prochain article de ce guide, nous explorerons comment les différents widgets de formulaire HTML prennent en charge les plus importantes propriétés des CSS : <a class="new" href="https://developer.mozilla.org/fr/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets" rel="nofollow">Tableau de compatibilité des propriétés entre widgets de formulaire</a>.</p> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li><a href="http://diveintohtml5.info/forms.html" rel="external" title="http://diveintohtml5.info/forms.html">Dive into HTML5: Forms </a>(en anglais)</li> + <li><a href="http://www.smashingmagazine.com/2011/06/27/useful-ideas-and-guidelines-for-good-web-form-design/" rel="external" title="http://www.smashingmagazine.com/2011/06/27/useful-ideas-and-guidelines-for-good-web-form-design/">Idées utiles et lignes‑guides pour un bon design des formulaires Web</a> (en anglais)</li> +</ul> + +<p>{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML", "Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets", "Web/Guide/HTML/Formulaires")}}</p> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML">Mon premier formulaire HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML"><span>Comment structurer un formulaire HTML</span></a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">Les widgets natifs pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets personnalisés pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">Mise en forme des formulaires HTML</a></li> + <li>Mise en forme avancée des formulaires HTML</li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Table de compatibilité des propriétés pour les widgets de formulaire</a></li> +</ul> diff --git a/files/fr/web/guide/html/formulaires/apparence_des_formulaires_html/index.html b/files/fr/web/guide/html/formulaires/apparence_des_formulaires_html/index.html new file mode 100644 index 0000000000..fbdafe47d4 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/apparence_des_formulaires_html/index.html @@ -0,0 +1,391 @@ +--- +title: Mise en forme des formulaires HTML +slug: Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML +tags: + - CSS + - Exemple + - Formulaires + - Guide + - HTML + - Intermédiaire + - Web +translation_of: Learn/Forms/Styling_web_forms +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers", "Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms", "Web/Guide/HTML/Formulaires")}}</div> + +<blockquote> +<p>Dans cet article, nous allons apprendre comment utiliser <a href="/fr/docs/CSS" title="/fr/docs/CSS">les CSS</a> avec les formulaires <a href="/fr/docs/HTML" title="/fr/docs/HTML">HTML</a> pour (espérons-le) améliorer leur apparence. Étonnamment, ceci peut être délicat. Pour des raisons techniques et historiques, les widgets de formulaires ne s'allient pas très bien avec CSS. À cause de ces difficultés, de nombreux développeurs préfèrent <a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés" title="/fr/docs/HTML/Formulaires/Comment_créer_des_blocs_de_formulaires_personnalisés">construire leurs propres widgets HTML</a> pour avoir plus de maîtrise sur leur apparence. Toutefois, avec les navigateurs modernes, les web designers ont de plus en plus d'emprise sur l'apparence de leurs formulaires. Voyons cela de plus près.</p> +</blockquote> + +<h2 id="Pourquoi_est-ce_si_difficile_de_modifier_l'apparence_des_formulaires_avec_CSS">Pourquoi est-ce si difficile de modifier l'apparence des formulaires avec CSS ?</h2> + +<p>Dans la jeunesse du Web — aux alentours de 1995 — les formulaires ont été ajoutés au HTML dans la <a href="http://www.ietf.org/rfc/rfc1866.txt" rel="extrenal" title="http://www.ietf.org/rfc/rfc1866.txt">spécification HTML 2</a>. À cause de la complexité des formulaires, ceux qui les mettaient en œuvre ont préféré s'appuyer sur le système d'exploitation sous‑jacent pour les gérer et les afficher.</p> + +<p>Quelques années plus tard, les CSS ont été créées et ce qui était une nécessité technique — c'est-à-dire, utiliser des widgets natifs pour les contrôles de formulaire — est devenu un préalable stylistique. Dans la jeunesse des CSS, l'apparence des formulaires n'était pas une priorité.</p> + +<p>Comme les utilisateurs étaient habitués à l'apparence visuelle de leurs plateformes respectives, les fournisseurs de navigateurs étaient réticents à rendre possible la modification de l'apparence des formulaires. Et pour être honnête, il est toujours extrêmement difficile de reconstruire tous les contrôles pour que leur apparence soit modifiable.</p> + +<p>Même aujourd'hui, aucun des navigateurs n'a entièrement mis en œuvre les CSS 2.1. Avec le temps, les fournisseurs de navigateurs ont toutefois amélioré la compatibilité des CSS avec les éléments de formulaires, et bien que ce soit de mauvaise réputation pour leur utilisation, vous pouvez désormais modifier l'apparence des <a href="/fr/docs/Web/Guide/HTML/Formulaires" title="/fr/docs/HTML/Formulaires">formulaires HTML</a>.</p> + +<h3 id="Tous_les_widgets_ne_sont_pas_égaux_devant_les_CSS">Tous les widgets ne sont pas égaux devant les CSS</h3> + +<p>Actuellement, quelques difficultés subsistent dans l'utilisation des CSS avec les formulaires. Ces problèmes peuvent être classés en trois catégories.</p> + +<h4 id="Le_bon">Le bon</h4> + +<p>L'apparence de certains éléments peut être modifiée sans poser beaucoup de problèmes suivant les diverses plateformes. Ceci inclut les éléments structurels suivants :</p> + +<ol> + <li>{{HTMLElement("form")}}</li> + <li>{{HTMLElement("fieldset")}}</li> + <li>{{HTMLElement("label")}}</li> + <li>{{HTMLElement("output")}}</li> +</ol> + +<p>Ceci inclut aussi tous les widgets de champs textuels (qu'ils soient mono ou multi‑lignes), ainsi que les boutons.</p> + +<h4 id="La_brute">La brute</h4> + +<p>L'apparence de certains éléments ne peut être modifiée que rarement et peut nécessiter quelques astuces complexes, et parfois une connaissance avancée des CSS3.</p> + +<p>Ceci inclut l'élément {{HTMLElement("legend")}}. Ce dernier ne peut pas être positionné correctement sur toutes les plateformes. De plus, l'apparence des cases à cocher et des boutons radio ne peut pas être modifiée directement. Toutefois, grâce à CSS3 c'est possible de contourner cette limitation. L'apparence du contenu {{htmlattrxref("placeholder", "input")}} ne peut pas être modifiée d'une manière standard. Mais tous les navigateurs qui sont compatible avec cet attribut ont aussi implémenté des pseudo-classes ou pseudo-élément propriétaires qui permettent de modifier son apparence.</p> + +<p>Nous allons voir comment gérer ces cas particuliers dans l'article <a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms" title="/fr/docs/HTML/Formulaires/Apparence_avancée_des_formulaires_HTML">Apparence avancée des formulaires HTML</a>.</p> + +<h4 id="Le_truand">Le truand</h4> + +<p>L'apparence de certains éléments n'est tout bonnement pas modifiable en utilisant les CSS. Ceci inclut toutes les interfaces avancées comme les intervalles, la sélection de couleur ou de date ainsi que les éléments déroulants, y compris les éléments {{HTMLElement("select")}}, {{HTMLElement("option")}}, {{HTMLElement("optgroup")}} et {{HTMLElement("datalist")}}. La sélection de fichiers est aussi connue pour ne pas pouvoir changer d'apparence. Les nouveaux éléments {{HTMLElement("progress")}} et {{HTMLElement("meter")}} font aussi partie de cette catégorie.</p> + +<p>Le principal problème avec tous ces widgets vient du fait que leur structure est très complexe et les CSS n'ont pas assez d'expressions pour décrire et modifier l'apparence des éléments. Si vous souhaitez modifier l'apparence des widgets vous devez utiliser JavaScript pour construire une arborescence DOM qui vous permet de modifier l'apparence. Nous explorons cette possibilité dans l'article <a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés" title="/fr/docs/HTML/Formulaires/Comment_créer_des_blocs_de_formulaires_personnalisés">Comment créer des widgets de formulaire personnalisés</a>.</p> + +<h2 id="Compositions_stylistiques_de_base">Compositions stylistiques de base</h2> + +<p>Pour changer l'apparence <a href="/fr/docs/HTML/Formulaires/Apparence_des_formulaires_HTML#Le_bon" title="/fr/docs/HTML/Formulaires/Apparence_des_formulaires_HTML#Le_bon">des éléments facilement modifiables</a> avec les CSS, vous ne devriez pas rencontrer de problèmes, puisqu'ils se comportent comme n'importe quel autre élément HTML. Toutefois, les feuilles de style peuvent ne pas être cohérentes entre navigateurs, il y a donc un certain nombre d'astuces à connaître.</p> + +<h3 id="Champs_de_recherche">Champs de recherche</h3> + +<p>Les boîtes de recherche sont le seul type de champ textuel dont l'apparence peut être un peu complexe à modifier. Sur les navigateurs utilisant WebKit (Chrome, Safari, etc.) vous devrez utiliser la propriété CSS propriétaire <code>-webkit-appearance</code>. Nous allons aborder le sujet plus en détails dans dans l'article : <a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms" title="/fr/docs/Apparence_avancée_des_formulaires_HTML">Apparence avancée des formulaires HTML</a>.</p> + +<h4 id="Exemple">Exemple</h4> + +<pre class="brush: html"><form> + <input type="search"> +</form> +</pre> + +<pre class="brush: css">input[type=search] { + border: 1px dotted #999; + border-radius: 0; + + -webkit-appearance: none; +}</pre> + +<p><img alt="This is a screenshot of a search filed on Chrome, with and without the use of -webkit-appearance" src="/files/4153/search-chrome-macos.png" style="border-style: solid; border-width: 1px; height: 107px; width: 179px;"></p> + +<p>Comme vous pouvez le voir sur la capture d'écran pour Chrome, les deux champs ont une bordure, mais le premier champ n'utilise pas la propriété <code>-webkit-appearance</code> tandis que le second a recours à la propriété <code>-webkit-appearance:none</code>. La différence est notable.</p> + +<h3 id="Texte_et_polices_de_caractères">Texte et polices de caractères</h3> + +<p>Les fonctionnalités liées au texte et aux polices de caractères dans les CSS peuvent être utilisées facilement avec n'importe quel widget (et oui, vous pouvez utiliser {{cssxref("@font-face")}} avec les formulaires). Toutefois, le comportement des navigateurs est souvent incompatible. Par défaut, certains éléments comme {{cssxref("font-family")}} {{cssxref("font-size")}} n'héritent pas de leurs parents. De nombreux navigateurs utilisent les valeurs du système d'exploitation. Pour que l'apparence des formulaires soit cohérente avec le reste de votre contenu, vous pouvez ajouter les règles suivantes à votre feuille de style :</p> + +<pre class="brush: css">button, input, select, textarea { + font-family : inherit; + font-size : 100%; +}</pre> + +<p>La capture d'écran ci-dessous montre les différences. Sur la gauche il y a l'affichage par défaut de Firefox pour Mac OS X, avec les réglages de police par défaut du système. Sur la droite, les mêmes éléments avec la règle d'harmonisation utilisée.</p> + +<p><img alt="This is a screenshot of the main form widgets on Firefox on Mac OSX, with and without font harmonization" src="/files/4157/font-firefox-macos.png" style="border-style: solid; border-width: 1px; height: 234px; width: 420px;"></p> + +<p>Il existe un débat animé sur le fait qu'un formulaire ait une meilleure apparence en utilisant les valeurs par défaut du système d'exploitation ou en utilisant des valeurs unifiant l'apparence. C'est à vous de décider en tant que designer du site ou de l'application.</p> + +<h3 id="Modèle_de_boîte">Modèle de boîte</h3> + +<p>Tous les champs textuels sont compatibles avec les différentes propriétés du modèle de boîte CSS ({{cssxref("width")}}, {{cssxref("height")}}, {{cssxref("padding")}}, {{cssxref("margin")}} et {{cssxref("border")}}). Toutefois, comme précédemment les navigateurs s'appuient sur l'apparence par défaut du système d'exploitation. C'est votre décision de choisir si vous souhaitez intégrer vos formulaires à votre contenu du point de vue de l'apparence. Si vous souhaitez conserver l'apparence originale des blocs, vous aurez des difficultés à leur donner des dimensions cohérentes.</p> + +<p><strong>Chacun des blocs a ses propres règles concernant les bordures, la marge intérieure (padding) et extérieure (margin).</strong> Si vous souhaitez qu'ils aient tous la même dimension, vous devrez utiliser la propriété {{cssxref("box-sizing")}} :</p> + +<pre class="brush: css">input, textarea, select, button { + width : 150px; + margin: 0; + + -webkit-box-sizing: border-box; /* Pour les anciennes versions des navigateurs WebKit */ + -moz-box-sizing: border-box; /* Pour tous les navigateurs Gecko */ + box-sizing: border-box; +}</pre> + +<p><img alt="This is a screenshot of the main form widgets on Chrome on Windows 7, with and without the use of box-sizing." src="/files/4161/size-chrome-win7.png" style="border-style: solid; border-width: 1px; height: 213px; width: 358px;"></p> + +<p>Dans la capture d'écran ci-dessous, la colonne de gauche n'utilise pas {{cssxref("box-sizing")}}, alors que la colonne de droite utilise la propriété CSS <code>border-box</code>. Remarquez comment tous les éléments occupent le même espace, malgré les valeurs par défaut de la plateforme pour chacun des blocs.</p> + +<h3 id="Positionnement">Positionnement</h3> + +<p>Le positionnement des formulaires HTML n'est pas un problème de manière générale. Seulement deux éléments nécessitent une attention particulière :</p> + +<h4 id="legend">legend</h4> + +<p>L'apparence de l'élément {{HTMLElement("legend")}} est facile à modifier à l'exception de sa position. Dans chaque navigateur, l'élément {{HTMLElement("legend")}} est positionné au-dessus de la bordure supérieure de son élément {{HTMLElement("fieldset")}} parent. Il n'existe aucune manière de changer sa position dans le flux HTML. Vous pouvez toutefois le positionner de manière absolue ou relative en utilisant la propriété {{cssxref("position")}}, sinon, ce sera une partie de la bordure de l'élément <code>fieldset</code>.</p> + +<p>Comme l'élément {{HTMLElement("legend")}} est très important pour des raisons d'accessibilité (nous parlerons des techniques pour l'assistance à propos de l'attribut <code>label</code> de chaque élément de formulaire du <code>fieldset</code>), il est souvent associé à un intitulé, puis caché à l'accessibilité, comme ceci :</p> + +<h5 id="HTML">HTML</h5> + +<pre class="brush: html"><fieldset> + <legend>Hi!</legend> + <h1>Hello</h1> +</fieldset></pre> + +<h5 id="CSS">CSS</h5> + +<pre class="brush: css">legend { + width: 1px; + height: 1px; + overflow: hidden; +}</pre> + +<h4 id="textarea">textarea</h4> + +<p>Par défaut, tous les navigateurs considèrent l'élément {{HTMLElement("textarea")}} comme un bloc incorporé aligné sur la ligne du bas du texte. C'est rarement ce que nous souhaitons vraiment. Pour passer d<code>'inline-block</code> à <code>block</code>, il est assez facile d'utiliser la propriété {{cssxref("display")}}. Mais si vous voulez l'utiliser en ligne, il est courant de changer son alignement vertical :</p> + +<pre class="brush: css">textarea { + vertical-align: top; +}</pre> + +<h2 id="Exemple_2">Exemple</h2> + +<p>Regardons sur un exemple concret la façon de composer un formulaire HTML. Cela aidera à clarifier nombre de ces concepts. Nous allons construire un formulaire de contact sous forme de « carte postale » :</p> + +<p><img alt="C'est ce que nous voulons réaliser avec le HTML et les CSS." src="https://mdn.mozillademos.org/files/16012/fr-carte.png" style="border-style: solid; border-width: 1px; height: 315px; width: 465px;"></p> + +<h3 id="HTML_2">HTML</h3> + +<p>Le HTML n'est qu'à peine plus développé que celui de l'exemple du premier<a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML" title="/en-US/docs/HTML/Forms/My_first_HTML_form"> article de ce guide</a> ; il ne comporte que quelques identifiants supplémentaires et un titre.</p> + +<pre class="brush: html"><form> + <h1>à: Mozilla</h1> + + <div id="from"> + <label for="name">de :</label> + <input type="text" id="name" name="user_name"> + </div> + + <div id="reply"> + <label for="mail">répondre à :</label> + <input type="email" id="mail" name="user_email"> + </div> + + <div id="message"> + <label for="msg">Votre message :</label> + <textarea id="msg" name="user_message"></textarea> + </div> + + <div class="button"> + <button type="submit">Poster le message</button> + </div> +</form></pre> + +<h3 id="Organiser_les_ressources">Organiser les ressources</h3> + +<p>C'est ici que le « fun » commence ! Avant de commencer à coder, nous avons besoin de trois ressources supplémentaires :</p> + +<ol> + <li>L'<a href="/files/4151/background.jpg" title="The postcard background">image de fond</a> de la carte postale — téléchargez cette image et sauvegardez‑la dans le même répertoire que votre fichier HTML de travail.</li> + <li>Une police de machine à écrire : <a href="http://www.fontsquirrel.com/fonts/Secret-Typewriter" rel="external" title="http://www.fontsquirrel.com/fonts/Secret-Typewriter">« Secret Typewriter » de fontsquirrel.com</a> — téléchargez le fichier TTF dans le même répertoire que ci‑dessus.</li> + <li>Une police d'écriture manuelle : <a href="http://www.fontsquirrel.com/fonts/Journal" rel="external" title="http://www.fontsquirrel.com/fonts/Journal"> « Journal » de fontsquirrel.com </a>— téléchargez le fichier TTF dans le même répertoire que ci‑dessus.</li> +</ol> + +<p> </p> + +<p>Les polices demandent un supplément de traitement avant de débuter :</p> + +<ol> + <li>Allez sur le <a href="https://www.fontsquirrel.com/tools/webfont-generator">Webfont Generator</a> de fontsquirrel.</li> + <li>En utilisant le formulaire, téléversez les fichiers de polices et créez un kit de polices pou le Web. Téléchargez le kit sur votre ordinateur.</li> + <li>Décompressez le fichier zip fourni.</li> + <li>Dans le contenu décompressé vous trouverez deux fichiers <code>.woff</code> et deux fichiers <code>.woff2</code>. Copiez ces quatre fichiers dans un répertoire nommé <code>fonts</code>, dans le même répertoire que ci‑dessus. Nous utilisons deux fichiers différents pour maximiser la compatibilité avec les navigateurs ; voyez notre article sur les <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/Styling_text/Web_fonts">Web fonts</a> pour des informations plus détaillées.</li> +</ol> + +<h3 id="Le_CSS">Le CSS</h3> + +<p> </p> + +<p>Maintenant nous pouvons approfondir les CSS de l'exemple. Ajoutez tous les blocs de code affichés ci‑dessous dans un élément {{htmlelement("style")}}, l'un après l'autre.</p> + +<p>D'abord, la préparation de base en définissant les règles de {{cssxref("@font-face")}} et les base des éléments {{HTMLElement("body")}} et {{HTMLElement("form")}}.</p> + +<pre class="brush: css">@font-face{ + font-family : "handwriting"; +<code class="language-css"><span class="property token"> src</span><span class="punctuation token">:</span> <span class="token url">url('fonts/journal-webfont.woff2')</span> <span class="function token">format</span><span class="punctuation token">(</span><span class="string token">'woff2'</span><span class="punctuation token">)</span>, + <span class="token url">url('fonts/journal-webfont.woff')</span> <span class="function token">format</span><span class="punctuation token">(</span><span class="string token">'woff'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="property token">font-weight</span><span class="punctuation token">:</span> normal<span class="punctuation token">;</span> + <span class="property token">font-style</span><span class="punctuation token">:</span> normal<span class="punctuation token">;</span></code> +} + +@font-face{ + font-family : "typewriter"; +<code class="language-css"> <span class="property token">src</span><span class="punctuation token">:</span> <span class="token url">url('fonts/veteran_typewriter-webfont.woff2')</span> <span class="function token">format</span><span class="punctuation token">(</span><span class="string token">'woff2'</span><span class="punctuation token">)</span>, + <span class="token url">url('fonts/veteran_typewriter-webfont.woff')</span> <span class="function token">format</span><span class="punctuation token">(</span><span class="string token">'woff'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="property token">font-weight</span><span class="punctuation token">:</span> normal<span class="punctuation token">;</span> + <span class="property token">font-style</span><span class="punctuation token">:</span> normal<span class="punctuation token">;</span></code> +} + +body { + font : 21px sans-serif; + + padding : 2em; + margin : 0; + + background : #222; +} + +form { + position: relative; + + width : 740px; + height : 498px; + margin : 0 auto; + + background: #FFF url(background.jpg); +}</pre> + +<p>Maintenant nous pouvons placer nos éléments, y compris le titre et tous les éléments du formulaire.</p> + +<pre class="brush: css">h1 { + position : absolute; + left : 415px; + top : 185px; + + font : 1em "typewriter", sans-serif; +} + +#from { + position: absolute; + left : 398px; + top : 235px; +} + +#reply { + position: absolute; + left : 390px; + top : 285px; +} + +#message { + position: absolute; + left : 20px; + top : 70px; +}</pre> + +<p>C'est là que nous commençons à travailler sur les éléments du formulaire eux-mêmes. Tout d'abord, assurons-nous que l'élément {{HTMLElement("label")}} est doté de la bonne police de caractères.</p> + +<pre class="brush: css">label { + font : .8em "typewriter", sans-serif; +}</pre> + +<p>Les champs texte nécessitent quelques règles courantes. Mettons‑les simplement, nous supprimons {{cssxref("border","borders")}} et {{cssxref("background","backgrounds")}} et redéfinissons {{cssxref("padding")}} et {{cssxref("margin")}}.</p> + +<pre class="brush: css">input, textarea { + font : .9em/1.5em "handwriting", sans-serif; + + border : none; + padding : 0 10px; + margin : 0; + width : 240px; + + background: none; +}</pre> + +<p>Lorsque l'un de ces champs reçoit le focus, nous le mettons en évidence avec un fond gris clair et transparent. Notez qu'il est important d'ajouter la propriété {{cssxref("outline")}} pour supprimer le focus par défaut ajouté par certains navigateurs.</p> + +<pre class="brush: css">input:focus, textarea:focus { + background : rgba(0,0,0,.1); + border-radius: 5px; + outline : none; +}</pre> + +<p>Maintenant que nos champs texte sont terminés, nous devons ajuster l'affichage de ceux à une et ceux à plusieurs lignes pour qu'ils correspondent, car ils ne sont généralement pas du tout identiques par défaut.</p> + +<p>Le champ texte à une seule ligne a besoin de quelques ajustements pour un bon rendu dans Internet Explorer. Internet Explorer ne définit pas la hauteur des champs en fonction de la hauteur naturelle de la police (qui est le comportement de tous les autres navigateurs). Pour résoudre ce problème, nous devons ajouter une hauteur explicite au champ, comme suit :</p> + +<pre class="brush: css">input { + height: 2.5em; /* pour IE */ + vertical-align: middle; /* optionnel mais donne meilleur aspect pour IE */ +}</pre> + +<p>Les éléments {{HTMLElement("textarea")}} sont rendus par défaut en tant qu'élément bloc. Les deux choses importantes ici sont les propriétés {{cssxref("resize")}} et {{cssxref("overflow")}}. Comme notre design est à taille fixe, nous utiliserons la propriété resize pour empêcher les utilisateurs de redimensionner le champ texte multiligne. La propriété {{cssxref("overflow")}} est utilisée pour rendre le champ plus cohérent d'un navigateur à l'autre ; certains navigateurs utilisent la valeur <code>auto</code> et d'autres la valeur par défaut pour <code>scroll</code> lorsqu'elle n'est pas précisée. Dans notre cas, il vaut mieux s'assurer que tout le monde utilise <code>auto</code>.</p> + +<pre class="brush: css">textarea { + display : block; + + padding : 10px; + margin : 10px 0 0 -10px; + width : 340px; + height : 360px; + + resize : none; + overflow: auto; +}</pre> + +<p>L'élément {{HTMLElement("button")}} est très accommodant avec les CSS ; vous faites ce que vous voulez, même en utilisant les <a href="/en-US/docs/CSS/Pseudo-elements" title="/en-US/docs/CSS/Pseudo-elements">pseudo-elements</a> !</p> + +<pre class="brush: css">button { + position : absolute; + left : 440px; + top : 360px; + + padding : 5px; + + font : bold .6em sans-serif; + border : 2px solid #333; + border-radius: 5px; + background : none; + + cursor : pointer; + +-webkit-transform: rotate(-1.5deg); + -moz-transform: rotate(-1.5deg); + -ms-transform: rotate(-1.5deg); + -o-transform: rotate(-1.5deg); + transform: rotate(-1.5deg); +} + +button:after { + content: " >>>"; +} + +button:hover, +button:focus { + outline : none; + background: #000; + color : #FFF; +}</pre> + +<p>Et voilà ! (en français dans le texte)</p> + +<div class="note"> +<p><strong>Note :</strong> si cet exemple ne fonctionne pas tout à fait comme vous l'attendez et que vous voulez vérifier votre version, vous la trouverez sur GitHub — voyez‑la <a href="https://mdn.github.io/learning-area/html/forms/postcard-example/">fonctionner en direct</a> (et revoyez son <a href="https://github.com/mdn/learning-area/tree/master/html/forms/postcard-example">code source</a>).</p> +</div> + +<h2 id="Conclusion">Conclusion</h2> + +<p>Comme vous pouvez le voir, tant que nous voulons construire des formulaires avec seulement des champs de texte et des boutons, il est facile de les styliser à l'aide des CSS. Si vous voulez en savoir plus sur les petites astuces des CSS qui peuvent vous faciliter la vie lorsque vous travaillez avec des widgets de formulaire, jetez un coup d'oeil à la partie formulaire du <a href="http://necolas.github.com/normalize.css">projet normalize.css</a>.</p> + +<p>Dans le <a href="/fr/docs/Web/Guide/HTML/Forms/Advanced_styling_for_HTML_forms">prochain article</a>, nous verrons comment gérer les widgets des catégories « brutes » et « truands ».</p> + +<p>{{PreviousMenuNext("Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers", "Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms", "Web/Guide/HTML/Formulaires")}}</p> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML">Mon premier formulaire HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML"><span>Comment structurer un formulaire HTML</span></a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">Les widgets natifs pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets personnalisés pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></li> + <li>Mise en forme des formulaires HTML</li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">Mise en forme avancée des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Table de compatibilité des propriétés pour les widgets de formulaire</a></li> +</ul> diff --git a/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/example_3/index.html b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/example_3/index.html new file mode 100644 index 0000000000..a647cfaba3 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/example_3/index.html @@ -0,0 +1,247 @@ +--- +title: Exemple 3 +slug: >- + Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Example_3 +tags: + - Formulaires + - HTML +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_3 +--- +<p>Ceci est le troisième exemple expliquant comment <a href="https://developer.mozilla.org/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">construire des widgets de formulaire personnalisés</a>.</p> + +<h2 id="Change_states" name="Change_states">Changement d'état</h2> + +<h3 id="Contenu_HTML">Contenu HTML</h3> + +<pre class="brush: html"><form class="no-widget"> + <select name="myFruit" tabindex="-1"> + <option>Cerise</option> + <option>Citron</option> + <option>Banane</option> + <option>Fraise</option> + <option>Pomme</option> + </select> + + <div class="select" tabindex="0"> + <span class="value">Cerise</span> + <ul class="optList hidden"> + <li class="option">Cerise</li> + <li class="option">Citron</li> + <li class="option">Banane</li> + <li class="option">Fraise</li> + <li class="option">Pomme</li> + </ul> + </div> +</form></pre> + +<h3 id="Contenu_du_CSS">Contenu du CSS</h3> + +<pre class="brush: css">.widget select, +.no-widget .select { + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +} + +/* --------------- */ +/* Styles Requis */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Style chic */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<h3 id="Contenu_JavaScript">Contenu JavaScript</h3> + +<pre class="brush: js">// ----------- // +// UTILITAIRES // +// ----------- // + +NodeList.prototype.forEach = function (callback) { + Array.prototype.forEach.call(this, callback); +} + +// ------------------------- // +// Définitions des fonctions // +// ------------------------- // + +function deactivateSelect(select) { + if (!select.classList.contains('active')) return; + + var optList = select.querySelector('.optList'); + + optList.classList.add('hidden'); + select.classList.remove('active'); +} + +function activeSelect(select, selectList) { + if (select.classList.contains('active')) return; + + selectList.forEach(deactivateSelect); + select.classList.add('active'); +}; + +function toggleOptList(select, show) { + var optList = select.querySelector('.optList'); + + optList.classList.toggle('hidden'); +} + +function highlightOption(select, option) { + var optionList = select.querySelectorAll('.option'); + + optionList.forEach(function (other) { + other.classList.remove('highlight'); + }); + + option.classList.add('highlight'); +}; + +// ------------------- // +// Lien aux événements // +// ------------------- // + +window.addEventListener("load", function () { + var form = document.querySelector('form'); + + form.classList.remove("no-widget"); + form.classList.add("widget"); +}); + +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + selectList.forEach(function (select) { + var optionList = select.querySelectorAll('.option'); + + optionList.forEach(function (option) { + option.addEventListener('mouseover', function () { + highlightOption(select, option); + }); + }); + + select.addEventListener('click', function (event) { + toggleOptList(select); + }, false); + + select.addEventListener('focus', function (event) { + activeSelect(select, selectList); + }); + + select.addEventListener('blur', function (event) { + deactivateSelect(select); + }); + }); +});</pre> + +<h3 id="Résultat">Résultat</h3> + +<p>{{ EmbedLiveSample('Change_states') }}</p> diff --git a/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/example_4/index.html b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/example_4/index.html new file mode 100644 index 0000000000..4bd1a9a069 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/example_4/index.html @@ -0,0 +1,297 @@ +--- +title: Exemple 4 +slug: >- + Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Example_4 +tags: + - Avancé + - Exemple + - Formulaires + - Guide + - HTML + - Web +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_4 +--- +<p>Ceci est le quatrième exemple expliquant <a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">comment construire des widgets de formulaire personnalisés</a>.</p> + +<h2 id="Change_states" name="Change_states">Changement d'état</h2> + +<h3 id="Contenu_HTML">Contenu HTML</h3> + +<pre class="brush: html"><form class="no-widget"> + <select name="myFruit"> + <option>Cerise</option> + <option>Citron</option> + <option>Banane</option> + <option>Fraise</option> + <option>Pomme</option> + </select> + + <div class="select"> + <span class="value">Cerise</span> + <ul class="optList hidden"> + <li class="option">Cerise</li> + <li class="option">Citron</li> + <li class="option">Banane</li> + <li class="option">Fraise</li> + <li class="option">Pomme</li> + </ul> + </div> +</form></pre> + +<h3 id="Contenu_CSS">Contenu CSS</h3> + +<pre class="brush: css">.widget select, +.no-widget .select { + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +} + +/* --------------- */ +/* Styles Requis */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Styles chic */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<h3 id="Contenu_JavaScript">Contenu JavaScript</h3> + +<pre class="brush: js">// ----------- // +// UTILITAIRES // +// ----------- // + +NodeList.prototype.forEach = function (callback) { + Array.prototype.forEach.call(this, callback); +} + +// ------------------------- // +// Définitions des fonctions // +// ------------------------- // + +function deactivateSelect(select) { + if (!select.classList.contains('active')) return; + + var optList = select.querySelector('.optList'); + + optList.classList.add('hidden'); + select.classList.remove('active'); +} + +function activeSelect(select, selectList) { + if (select.classList.contains('active')) return; + + selectList.forEach(deactivateSelect); + select.classList.add('active'); +}; + +function toggleOptList(select, show) { + var optList = select.querySelector('.optList'); + + optList.classList.toggle('hidden'); +} + +function highlightOption(select, option) { + var optionList = select.querySelectorAll('.option'); + + optionList.forEach(function (other) { + other.classList.remove('highlight'); + }); + + option.classList.add('highlight'); +}; + +function updateValue(select, index) { + var nativeWidget = select.previousElementSibling; + var value = select.querySelector('.value'); + var optionList = select.querySelectorAll('.option'); + + nativeWidget.selectedIndex = index; + value.innerHTML = optionList[index].innerHTML; + highlightOption(select, optionList[index]); +}; + +function getIndex(select) { + var nativeWidget = select.previousElementSibling; + + return nativeWidget.selectedIndex; +}; + +// -------------------- // +// Liens aux événements // +// -------------------- // + +window.addEventListener("load", function () { + var form = document.querySelector('form'); + + form.classList.remove("no-widget"); + form.classList.add("widget"); +}); + +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + selectList.forEach(function (select) { + var optionList = select.querySelectorAll('.option'); + + optionList.forEach(function (option) { + option.addEventListener('mouseover', function () { + highlightOption(select, option); + }); + }); + + select.addEventListener('click', function (event) { + toggleOptList(select); + }); + + select.addEventListener('focus', function (event) { + activeSelect(select, selectList); + }); + + select.addEventListener('blur', function (event) { + deactivateSelect(select); + }); + }); +}); + +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + selectList.forEach(function (select) { + var optionList = select.querySelectorAll('.option'), + selectedIndex = getIndex(select); + + select.tabIndex = 0; + select.previousElementSibling.tabIndex = -1; + + updateValue(select, selectedIndex); + + optionList.forEach(function (option, index) { + option.addEventListener('click', function (event) { + updateValue(select, index); + }); + }); + + select.addEventListener('keyup', function (event) { + var length = optionList.length, + index = getIndex(select); + + if (event.keyCode === 40 && index < length - 1) { index++; } + if (event.keyCode === 38 && index > 0) { index--; } + + updateValue(select, index); + }); + }); +});</pre> + +<h3 id="Résultat">Résultat</h3> + +<p>{{ EmbedLiveSample('Change_states') }}</p> diff --git a/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/example_5/index.html b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/example_5/index.html new file mode 100644 index 0000000000..bf1143d186 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/example_5/index.html @@ -0,0 +1,290 @@ +--- +title: Exemple 5 +slug: >- + Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Example_5 +tags: + - Formulaires + - HTML +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_5 +--- +<p>Voici le dernier exemple expliquant <a href="/fr/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">comment construire des widgets de formulaire personnalisés</a>.</p> + +<h2 id="Change_states" name="Change_states">Changement d'état</h2> + +<h3 id="Contenu_HTML">Contenu HTML</h3> + +<pre class="brush: html"><form class="no-widget"> + <select name="myFruit"> + <option>Cerise</option> + <option>Citron</option> + <option>Banane</option> + <option>Fraise</option> + <option>Pomme</option> + </select> + + <div class="select" role="listbox"> + <span class="value">Cerise</span> + <ul class="optList hidden" role="presentation"> + <li class="option" role="option" aria-selected="true">Cerise</li> + <li class="option" role="option">Citron</li> + <li class="option" role="option">Banane</li> + <li class="option" role="option">Fraise</li> + <li class="option" role="option">Pomme</li> + </ul> + </div> +</form></pre> + +<h3 id="Contenu_CSS">Contenu CSS</h3> + +<pre class="brush: css">.widget select, +.no-widget .select { + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +} + +/* --------------- */ +/* Styles Requis */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Styles Chic */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<h3 id="Contenu_JavaScript">Contenu JavaScript</h3> + +<pre class="brush: js">// ----------- // +// UTILITAIRES // +// ----------- // + +NodeList.prototype.forEach = function (callback) { + Array.prototype.forEach.call(this, callback); +} + +// ------------------------- // +// Définitions des fonctions // +// ------------------------- // + +function deactivateSelect(select) { + if (!select.classList.contains('active')) return; + + var optList = select.querySelector('.optList'); + + optList.classList.add('hidden'); + select.classList.remove('active'); +} + +function activeSelect(select, selectList) { + if (select.classList.contains('active')) return; + + selectList.forEach(deactivateSelect); + select.classList.add('active'); +}; + +function toggleOptList(select, show) { + var optList = select.querySelector('.optList'); + + optList.classList.toggle('hidden'); +} + +function highlightOption(select, option) { + var optionList = select.querySelectorAll('.option'); + + optionList.forEach(function (other) { + other.classList.remove('highlight'); + }); + + option.classList.add('highlight'); +}; + +function updateValue(select, index) { + var nativeWidget = select.previousElementSibling; + var value = select.querySelector('.value'); + var optionList = select.querySelectorAll('.option'); + + optionList.forEach(function (other) { + other.setAttribute('aria-selected', 'false'); + }); + + optionList[index].setAttribute('aria-selected', 'true'); + + nativeWidget.selectedIndex = index; + value.innerHTML = optionList[index].innerHTML; + highlightOption(select, optionList[index]); +}; + +function getIndex(select) { + var nativeWidget = select.previousElementSibling; + + return nativeWidget.selectedIndex; +}; + +// -------------------- // +// Liens aux événements // +// -------------------- // + +window.addEventListener("load", function () { + var form = document.querySelector('form'); + + form.classList.remove("no-widget"); + form.classList.add("widget"); +}); + +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + selectList.forEach(function (select) { + var optionList = select.querySelectorAll('.option'), + selectedIndex = getIndex(select); + + select.tabIndex = 0; + select.previousElementSibling.tabIndex = -1; + + updateValue(select, selectedIndex); + + optionList.forEach(function (option, index) { + option.addEventListener('mouseover', function () { + highlightOption(select, option); + }); + + option.addEventListener('click', function (event) { + updateValue(select, index); + }); + }); + + select.addEventListener('click', function (event) { + toggleOptList(select); + }); + + select.addEventListener('focus', function (event) { + activeSelect(select, selectList); + }); + + select.addEventListener('blur', function (event) { + deactivateSelect(select); + }); + + select.addEventListener('keyup', function (event) { + var length = optionList.length, + index = getIndex(select); + + if (event.keyCode === 40 && index < length - 1) { index++; } + if (event.keyCode === 38 && index > 0) { index--; } + + updateValue(select, index); + }); + }); +}); +</pre> + +<h3 id="Résultat">Résultat</h3> + +<p>{{ EmbedLiveSample('Change_states') }}</p> diff --git a/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/exemple_1/index.html b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/exemple_1/index.html new file mode 100644 index 0000000000..045f631079 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/exemple_1/index.html @@ -0,0 +1,420 @@ +--- +title: Exemple 1 +slug: >- + Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Exemple_1 +tags: + - Formulaires + - Guide + - HTML +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_1 +--- +<p>C'est le premier exemple de code qui explique <a href="/fr/docs/Web/Guide/HTML/Forms/How_to_build_custom_form_widgets">comment construire un widget de formulaire personnalisé</a>.</p> + +<h2 id="Basic_state" name="Basic_state">État initial</h2> + +<h3 id="Basic_state_HTML" name="Basic_state_HTML">HTML</h3> + +<pre class="brush: html"><div class="select"> + <span class="value">Cerise</span> + <ul class="optList hidden"> + <li class="option">Cerise</li> + <li class="option">Citron</li> + <li class="option">Banane</li> + <li class="option">Fraise</li> + <li class="option">Pomme</li> + </ul> +</div></pre> + +<h3 id="Basic_state_CSS" name="Basic_state_CSS">CSS</h3> + +<pre class="brush: css">/* --------------- */ +/* Styles Requis */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Style Chic */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFFFFF; +} +</pre> + +<h3 id="Resultat_pour_l'état_initial">Resultat pour l'état initial</h3> + +<div>{{ EmbedLiveSample("Basic_state", 120, 130) }}</div> + +<h2 id="Active_state" name="Active_state">État actif</h2> + +<h3 id="Active_state_HTML" name="Active_state_HTML">HTML</h3> + +<pre class="brush:html"><div class="select active"> + <span class="value">Cerise</span> + <ul class="optList hidden"> + <li class="option">Cerise</li> + <li class="option">Citron</li> + <li class="option">Banane</li> + <li class="option">Fraise</li> + <li class="option">Pomme</li> + </ul> +</div></pre> + +<h3 id="Active_state_CSS" name="Active_state_CSS">CSS</h3> + +<pre class="brush:css">/* --------------- */ +/* Styles Requis */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Style Chic */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<h3 id="Résultat_pour_état_actif">Résultat pour état actif</h3> + +<div>{{ EmbedLiveSample("Active_state", 120, 130) }}</div> + +<h2 id="Open_state" name="Open_state">État ouvert</h2> + +<h3 id="Open_state_HTML" name="Open_state_HTML">HTML</h3> + +<pre class="brush:html"><div class="select active"> + <span class="value">Cerise</span> + <ul class="optList"> + <li class="option highlight">Cerise</li> + <li class="option">Citron</li> + <li class="option">Banane</li> + <li class="option">Fraise</li> + <li class="option">Pomme</li> + </ul> +</div></pre> + +<h3 id="Open_state_CSS" name="Open_state_CSS">CSS</h3> + +<pre class="brush:css">/* --------------- */ +/* Styles Requis */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Style Chic */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0, 0, 0, .45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFF; +}</pre> + +<h3 id="Resultat_pour_état_ouvert">Resultat pour état ouvert</h3> + +<div>{{ EmbedLiveSample("Open_state", 120, 130) }}</div> diff --git a/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/exemple_2/index.html b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/exemple_2/index.html new file mode 100644 index 0000000000..dfb0eb3b6a --- /dev/null +++ b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/exemple_2/index.html @@ -0,0 +1,215 @@ +--- +title: Exemple 2 +slug: >- + Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Exemple_2 +tags: + - Formulaires + - HTML +translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_2 +--- +<p>Ceci est le deuxième exemple expliquant comment <a href="/fr/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">construire un formulaire personnalisé</a>.</p> + +<h2 id="JS" name="JS">JS</h2> + +<h3 id="HTML_Content">HTML Content</h3> + +<pre class="brush: html"><form class="no-widget"> + <select name="myFruit"> + <option>Cerise</option> + <option>Citron</option> + <option>Banane</option> + <option>Fraise</option> + <option>Pomme</option> + </select> + + <div class="select"> + <span class="value">Cerise</span> + <ul class="optList hidden"> + <li class="option">Cerise</li> + <li class="option">Citron</li> + <li class="option">Banane</li> + <li class="option">Fraise</li> + <li class="option">Pomme</li> + </ul> + </div> +<form> +</pre> + +<h3 id="CSS_Content">CSS Content</h3> + +<pre class="brush: css">.widget select, +.no-widget .select { + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +} + +/* --------------- */ +/* Styles requis */ +/* --------------- */ + +.select { + position: relative; + display : inline-block; +} + +.select.active, +.select:focus { + box-shadow: 0 0 3px 1px #227755; + outline: none; +} + +.select .optList { + position: absolute; + top : 100%; + left : 0; +} + +.select .optList.hidden { + max-height: 0; + visibility: hidden; +} + +/* ------------ */ +/* Styles décor */ +/* ------------ */ + +.select { + font-size : 0.625em; /* 10px */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + padding : 0.1em 2.5em 0.2em 0.5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : 0.2em solid #000; /* 2px */ + border-radius : 0.4em; /* 4px */ + + box-shadow : 0 0.1em 0.2em rgba(0,0,0,.45); /* 0 1px 2px */ + + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + display : inline-block; + width : 100%; + overflow : hidden; + + white-space : nowrap; + text-overflow : ellipsis; + vertical-align: top; +} + +.select:after { + content : "▼"; + position: absolute; + z-index : 1; + height : 100%; + width : 2em; /* 20px */ + top : 0; + right : 0; + + padding-top : .1em; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + text-align : center; + + border-left : .2em solid #000; + border-radius: 0 .1em .1em 0; + + background-color : #000; + color : #FFF; +} + +.select .optList { + z-index : 2; + + list-style: none; + margin : 0; + padding: 0; + + background: #f0f0f0; + border: .2em solid #000; + border-top-width : .1em; + border-radius: 0 0 .4em .4em; + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); + + -moz-box-sizing : border-box; + box-sizing : border-box; + + min-width : 100%; + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; +} + +.select .option { + padding: .2em .3em; +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<h3 id="Contenu_JavaScript">Contenu JavaScript</h3> + +<pre class="brush: js">window.addEventListener("load", function () { + var form = document.querySelector('form'); + + form.classList.remove("no-widget"); + form.classList.add("widget"); +});</pre> + +<h3 id="Résultat_avec_JavaScript">Résultat avec JavaScript</h3> + +<p>{{ EmbedLiveSample('JS', 120, 130) }}</p> + +<h2 id="No_JS" name="No_JS">Sans JS</h2> + +<h3 id="HTML_Content_2">HTML Content</h3> + +<pre class="brush: html"><form class="no-widget"> + <select name="myFruit"> + <option>Cerise</option> + <option>Citron</option> + <option>Banane</option> + <option>Fraise</option> + <option>Pomme</option> + </select> + + <div class="select"> + <span class="value">Cerise</span> + <ul class="optList hidden"> + <li class="option">Cerise</li> + <li class="option">Citron</li> + <li class="option">Banane</li> + <li class="option">Fraise</li> + <li class="option">Pomme</li> + </ul> + </div> +<form></pre> + +<h3 id="CSS_Content_2">CSS Content</h3> + +<pre class="brush: css">.widget select, +.no-widget .select { + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +}</pre> + +<h3 id="Result_for_No_JS">Result for No JS</h3> + +<p>{{ EmbedLiveSample('No_JS', 120, 130) }}</p> + +<p> </p> diff --git a/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/index.html b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/index.html new file mode 100644 index 0000000000..4173ff9f9c --- /dev/null +++ b/files/fr/web/guide/html/formulaires/comment_construire_des_widgets_de_formulaires_personnalisés/index.html @@ -0,0 +1,837 @@ +--- +title: Comment construire des widgets de formulaires personnalisés +slug: >- + Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés +tags: + - Avancé + - Exemple + - Formulaires + - Guide + - HTML + - Web +translation_of: Learn/Forms/How_to_build_custom_form_controls +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Validation_donnees_formulaire", "Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript", "Web/Guide/HTML/Formulaires")}}</div> + +<p class="summary">Dans de nombreux cas les <a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">widgets de formulaires HTML disponibles</a> ne suffisent pas. Si vous voulez composer certains widgets dans un <a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">style avancé</a> tels que l'élément {{HTMLElement("select")}} ou si vous voulez leur donner des comportements personnalisés, vous n'avez pas d'autre choix que de créer vos propres widgets.</p> + +<p>Dans cet article, nous verrons comment construire un tel widget. Pour cela, nous allons travailler avec un exemple : reconstruire l'élément {{HTMLElement("select")}}.</p> + +<div class="note"> +<p><strong>Note :</strong> Nous nous resterons centrés sur la construction des widgets, et non sur la façon de rendre le code générique et réutilisable ; cela impliquerait une manipulation de code JavaScript et de DOM dans un contexte inconnu, et nous sortirions de la portée de cet article.</p> +</div> + +<h2 id="Conception_structure_et_sémantique">Conception, structure et sémantique</h2> + +<p>Avant de créer un widget personnalisé, il faut commencer par déterminer exactement ce que vous voulez. Vous gagnerez ainsi un temps précieux. En particulier, il est important de définir clairement tous les états de votre widget. Pour ce faire, il est bon de commencer par un widget existant dont les états et le comportement sont bien connus, afin que vous puissiez simplement les imiter autant que possible.</p> + +<p>Dans notre exemple, nous allons reconstruire l'élément {{HTMLElement("select")}}}. Voici le résultat que nous voulons atteindre :</p> + +<p><img alt="The three states of a select box" src="/files/4481/custom-select.png" style="height: 135px; width: 366px;"></p> + +<p>Cette capture d'écran montre les trois états principaux du widget : l'état normal (à gauche), l'état actif (au milieu) et l'état ouvert (à droite).</p> + +<p>En termes de comportement, nous voulons que notre widget soit utilisable aussi bien avec une souris qu'avec un clavier, comme n'importe quel widget natif. Commençons par définir comment le widget atteint chaque état :</p> + +<dl> + <dt>Le widget est dans son état normal :</dt> + <dd> + <ul> + <li>la page se charge</li> + <li>le widget était actif et l'utilisateur a cliqué quelque part en dehors du widget</li> + <li>le widget était actif et l'utilisateur a déplacé le focus sur un autre avec le clavier</li> + </ul> + </dd> +</dl> + +<p> </p> + +<dl> + <dd> + <div class="note"> + <p><strong>Note :</strong> Déplacer le focus dans la page entre les divers widgets se fait généralement en appuyant sur la touche de tabulation, mais ce n'est pas la norme partout. Par exemple, circuler parmi les liens sur une page se fait dans Safari par défaut en utilisant la <a href="http://www.456bereastreet.com/archive/200906/enabling_keyboard_navigation_in_mac_os_x_web_browsers/">combinaison Option+Tab</a>.</p> + </div> + </dd> + <dt>Le widget est sans son état actif :</dt> + <dd> + <ul> + <li>l'utilisateur clique sur lui</li> + <li>l'utilisateur presse la touche Tabulation et obtient le focus</li> + <li>le widget était dans l'état ouvert et l'utilisateur a cliqué dessus.</li> + </ul> + </dd> + <dt>Le widget est dans un état ouvert :</dt> + <dd> + <ul> + <li>le widget est dans un état autre que ouvert et l'utilisateur clique dessus.</li> + </ul> + </dd> +</dl> + +<p>Maintenant que nous savons comment changer les états du widget, il est important de définir comment changer la valeur du widget :</p> + +<dl> + <dt>La valeur change quand :</dt> + <dd> + <ul> + <li>l'utilisateur clique sur une option quand le widget est dans l'état ouvert</li> + <li>l'utilisateur presse la touche <kbd>↑</kbd> ou <kbd>↓</kbd> quand le widget est dans l'état actif</li> + </ul> + </dd> +</dl> + +<p>Enfin, définissons comment les options du widget doivent se comporter :</p> + +<ul> + <li>Quand le widget est ouvert, l'option sélectionnée est mise en valeur</li> + <li>Quand la souris est sur une option, l'option est mise en valeur et l'option précédemment mise en valeur revient à l'état normal</li> +</ul> + +<p>Pour les besoins de notre exemple, nous nous arrêterons là ; cependant, si vous êtes un lecteur attentif, vous remarquerez que certains comportements ne sont pas précisés. Par exemple, que pensez-vous qu'il se passe si l'utilisateur appuie sur la touche Tabulation alors que le widget est dans l'état ouvert ? La réponse est… rien. D'accord, le bon comportement semble évident mais le fait est que, comme il n'est pas défini dans nos spécifications, il est très facile de fermer les yeux sur ce comportement. Dans un travail collaboratif, lorsque les personnes concevant le comportement du widget sont différentes de celles qui le mettent en œuvre, cette démarche se vérifiera.</p> + +<p>Autre exemple amusant : que se passera-t-il si l'utilisateur presse les touches <kbd>↑</kbd> ou <kbd>↓</kbd> alors que le widget est à l'état ouvert ? Ici, c'est un peu plus délicat. Si vous considérez que l'état actif et l'état ouvert sont totalement différents, la réponse est encore une fois « rien ne se produira » parce que nous n'avons pas défini d'interactions clavier pour l'état ouvert. D'autre part, si vous considérez que l'état actif et l'état ouvert coïncident, la valeur peut changer mais l'option ne sera certainement pas mise en valeur en conséquence, encore une fois parce que nous n'avons pas défini d'interactions clavier sur les options lorsque le widget est dans son état ouvert (nous avons seulement défini ce qui doit se passer lorsque le widget est ouvert, mais rien après).</p> + +<p>Dans notre exemple, les spécifications manquantes sont évidentes et nous les traiterons, mais cela peut devenir un problème réel sur de nouveaux widgets exotiques, pour lesquels personne n'a la moindre idée de ce qu'est le bon comportement. Il est donc toujours bon de passer du temps à l'étape conception, car si vous définissez pauvrement le comportement, ou si vous oubliez de le définir, il sera très difficile de le redéfinir une fois les utilisateurs habitués. Si vous avez des doutes, demandez l'avis des autres, et si vous avez le budget pour cela, n'hésitez pas à <a href="https://fr.wikipedia.org/wiki/Test_utilisateur">faire des tests utilisateur</a>. Ce processus est appelé UX Design <span class="CLPzrc Y0NH2b">(<strong>U</strong>ser e<strong>X</strong>perience)</span>. Si vous voulez en savoir plus sur ce sujet, vous devriez consulter les ressources utiles suivantes :</p> + +<ul> + <li><a href="http://www.uxmatters.com/" rel="external" title="http://www.uxmatters.com/">UXMatters.com</a></li> + <li><a href="http://uxdesign.com/" rel="external" title="http://uxdesign.com/">UXDesign.com</a></li> + <li><a href="http://uxdesign.smashingmagazine.com/" rel="external" title="http://uxdesign.smashingmagazine.com/">The UX Design section of SmashingMagazine</a></li> +</ul> + +<div class="note"> +<p><strong>Note : </strong>De plus, dans la plupart des systèmes, il y a moyen d'ouvrir l'élément {{HTMLElement("select")}} pour voir tous les choix disponibles (c'est la même chose que de cliquer sur l'élément {{HTMLElement("select")}} avec une souris). Cela se fait avec <kbd>Alt</kbd>+<strong><kbd>↓</kbd></strong> sous Windows et n'a pas été implémenté dans notre exemple - mais il serait facile de le faire, car le mécanisme a déjà été implémenté pour l'événement <code>click</code>.</p> +</div> + +<h3 id="Definition_de_la_structure_HTML_et_de_la_sémantique">Definition de la structure HTML et de la sémantique</h3> + +<p>Maintenant que la fonctionnalité de base du widget a été décidée, il est temps de commencer à construire notre widget. La première étape consiste à définir sa structure HTML et à lui donner une sémantique de base. Voici ce dont nous avons besoin pour reconstruire un élément <select> :</p> + +<pre class="brush: html"><!-- Ceci est notre conteneur principal pour le widget. L'attribut tabindex + est ce qui permet à l'utilisateur de mettre le focus sur le widget. + Nous verrons plus loin que c'est mieux de le faire avec JavaScript. --> +<div class="select" tabindex="0"> + + <!-- Ce containeur sera utilisé pour afficher la valeur courante du widget --> + <span class="value">Cerise</span> + + <!-- Ce conteneur contiendra toutes les options disponibles pour le widget. + Comme c'est une liste, il y sens à utiliser l'élément ul. --> + <ul class="optList"> + <!-- Chaque option ne contient que la valeur à afficher, Nous verrons plus loin + comment gérer la valeur réelle qui sera envoyée avec les données du formulaire --> + <li class="option">Cerise</li> + <li class="option">Citron</li> + <li class="option">Banane</li> + <li class="option">Fraise</li> + <li class="option">Pomme</li> + </ul> + +</div></pre> + +<p>Notez l'utilisation de noms de classes qui identifient chaque partie pertinente indépendamment des éléments HTML sous-jacents utilisés. Ceci est important pour s'assurer que nous n'allons pas lier les CSS et JavaScript à une structure HTML forte, pour pouvoir faire des changements d'implémentation plus tard sans casser le code qui utilise le widget. Par exemple, si vous souhaitez implémenter l'équivalent de l'élément {{HTMLElement("optgroup")}}.</p> + +<h3 id="Composition_et_ressenti_avec_les_CSS">Composition et ressenti avec les CSS</h3> + +<p>Maintenant que nous avons une structure, nous pouvons commencer à concevoir notre widget. Le but de construire un widget personnalisé est de pouvoir lui donner exactement le style que nous voulons. Pour cela, nous allons partager le travail sur les CSS en deux parties : la première relative aux règles des CSS absolument nécessaires pour que notre widget se comporte comme un élément {{HTMLElement("select")}}, la seconde constituée des décorations utilisés lui donnant un aspect personnalisé.</p> + +<h4 id="Styles_obligatoires">Styles obligatoires</h4> + +<p>Les styles obligatoires sont ceux nécessaires à la gestion des trois états du widget.</p> + +<pre class="brush: css">.select { + /* Celui-ci crée un contexte de positionnement pour la liste des options */ + position: relative; + + /* Celui-ci fait que le widget devient partie du flot textuel + et devient en même temps dimensionnable */ + display : inline-block; +}</pre> + +<p>Nous avons besoin d'une classe <code>active</code> supplémentaire pour définir l'apparence du widget dans son état actif. Comme le widget peut recevoir le focus, nous doublons ce style personnalisé avec la pseudo-classe {{cssxref(":focus")}} afin d'être sûrs qu'elles se comporteront de la même manière.</p> + +<pre class="brush: css">.select.active, +.select:focus { + outline: none; + + /* Cette propriété box-shadow n'est pas requise à proprement parler, mais il est + important de s'assurer que l'état actif soit visible, c'est pourquoi nous + utilisons une valeur par défaut. Vous êtes libre de la modifier. */ + box-shadow: 0 0 3px 1px #227755; +}</pre> + +<p>Passons maintenant à la liste des options :</p> + +<pre class="brush: css">/* Le sélecteur .select ici est du sucre syntaxique (le fait de donner au + programmeur des possibilités d'écriture plus succinctes ou plus proches + d'une notation usuelle) pour s'assurer que les classes que nous définissons + sont les seules à l'intérieur du widget. */ +.select .optList { + /* Ceci assure que la liste des options sera affichée au dessous de la valeur + et en dehors du flot HTML */ + position : absolute; + top : 100%; + left : 0; +}</pre> + +<p>Nous avons besoin d'une classe supplémentaire pour gérer la liste d'options cachée. Ceci est nécessaire pour la gestion des différences entre état actif et état ouvert qui ne correspondent pas exactement.</p> + +<pre class="brush: css">.select .optList.hidden { + /* Ceci est un moyen simple pour cacher la liste tout en conservant l'accessibilité, + nous reparlerons plus loin d'accessibilité */ + max-height: 0; + visibility: hidden; +}</pre> + +<h4 id="Embellissements">Embellissements</h4> + +<p>Maintenant que nous avons mis en place les fonctionnalités de base, le divertissement peut commencer. Ce qui suit n'est qu'un exemple de ce qui est possible, et correspondra à la capture d'écran au début de cet article. Cependant, vous devriez vous sentir libre d'expérimenter et de voir ce que cela donne.</p> + +<pre class="brush: css">.select { + /* Toutes les tailles seront exprimées en valeurs em (lettre M, étalon + du cadratin : cadre dans lequel sont dessinées toutes les lettres d'une + police de caractères) pour des raisons d'accessibilité (pour être sûrs + que le widget reste redimensionnable si l'utilisateur utilise le zoom + du navigateur en mode texte exclusif). Les calculs sont faits en + supposant que 1em==16px qui est la valeur par défaut dans la majorité + des navigateurs. Si vous êtes perdus avec les conversions entre px et + em, essayez http://riddle.pl/emcalc/ */ + font-size : 0.625em; /* ceci (10px) est le nouveau contexte de taille de + police pour la valeur em dans ce contexte. */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + /* Nous avons besoin de plus d'espace pour la flèche vers le bas que nous + allons ajouter. */ + padding : .1em 2.5em .2em .5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : .2em solid #000; /* 2px */ + border-radius : .4em; /* 4px */ + box-shadow : 0 .1em .2em rgba(0,0,0,.45); /* 0 1px 2px */ + + /* La première déclaration concerne les navigateurs qui ne prennent pas en + charge les gradients linéaires. La deuxième déclaration est parce que + les navigateurs basés sur WebKit ne l'ont pas encore préfixé. Si vous + souhaitez prendre en charge les anciens navigateurs, essayez + http://www.colorzilla.com/gradient-editor/ */ + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + /* Comme la valeur peut être plus large que le widget, nous devons nous + assurer qu'elle ne changera pas la largeur du widget. */ + display : inline-block; + width : 100%; + overflow : hidden; + + vertical-align: top; + + /* Et si le contenu déborde, c'est mieux d'avoir une jolie abreviation. */ + white-space : nowrap; + text-overflow: ellipsis; +</pre> + +<p>Nous n'avons pas besoin d'un élément supplémentaire pour concevoir la flèche vers le bas ; à la place, nous utilisons le pseudo-élément {{cssxref(":after:after")}}. Cependant, elle pourrait également être mise en œuvre à l'aide d'une simple image de fond sur la classe <code>select</code>.</p> + +<pre class="brush: css">.select:after { + content : "▼"; /* Nous utilisons le caractère unicode U+25BC; + voir http://www.utf8-chartable.de */ + position: absolute; + z-index : 1; /* Il est important d'empêcher la flèche de chevaucher la liste des options */ + top : 0; + right : 0; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + height : 100%; + width : 2em; /* 20px */ + padding-top : .1em; /* 1px */ + + border-left : .2em solid #000; /* 2px */ + border-radius: 0 .1em .1em 0; /* 0 1px 1px 0 */ + + background-color : #000; + color : #FFF; + text-align : center; +}</pre> + +<p>Maintenant, composons la décoration de la liste des options :</p> + +<pre class="brush: css">.select .optList { + z-index : 2; /* Nous disons explicitement que la liste des options doit toujours passer sur la flèche */ + + /* cela réinitialiser le style par défaut de l'élément ul */ + list-style: none; + margin : 0; + padding: 0; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + /* Cela nous assure que même si les valeurs sont plus petites que le widget, + la liste des options sera aussi large que le widget lui‑même */ + min-width : 100%; + + /* Dans le cas où la liste est trop longue, son contenu débordera verticalement + (ce qui ajoutera une barre de déroulement automatiquement) mais jamais horizontalement + (car nous n'avons jamais défini de largeur, la liste ajustera automatiquement sa largeur + Si ce n'est pas possible, le contenu sera tronqué) */ + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; + + border: .2em solid #000; /* 2px */ + border-top-width : .1em; /* 1px */ + border-radius: 0 0 .4em .4em; /* 0 0 4px 4px */ + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); /* 0 2px 4px */ + background: #f0f0f0; +}</pre> + +<p>Pour les options, nous devons ajouter une classe <code>highlight</code> pour pouvoir identifier la valeur que l'utilisateur choisira (ou a choisi).</p> + +<pre class="brush: css">.select .option { + padding: .2em .3em; /* 2px 3px */ +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<p>Donc, voici le résultat avec les trois états :</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Basic state</th> + <th scope="col" style="text-align: center;">Active state</th> + <th scope="col" style="text-align: center;">Open state</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample('Basic_state',120,130, "", "Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Exemple_1")}}</td> + <td>{{EmbedLiveSample("Active_state",120,130, "", "Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Exemple_1")}}</td> + <td>{{EmbedLiveSample("Open_state",120,130, "", "Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Exemple_1")}}</td> + </tr> + <tr> + <td colspan="3" style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_1" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_1">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<h2 id="Donnez_vie_à_votre_widget_avec_JavaScript">Donnez vie à votre widget avec JavaScript</h2> + +<p>Maintenant que le design et la structure sont prêts, nous pouvons écrire le code JAvaScript pour que le widget fonctionne vraiment.</p> + +<div class="warning"> +<p>Avertissement : Le code qui suit a été conçu à des fins éducatives et ne doit pas être utilisé tel quel. Entre autres choses, comme nous le verrons, il n'est pas à l'épreuve du temps et ne fonctionnera pas sur des navigateurs historiques. Il comporte également des parties redondantes. Elles devraient être optimisées pour du code de production.</p> +</div> + +<div class="note"> +<p>Note : Créer des widgets réutilisables peut se révéler un peu délicat. L'ébauche de la norme « <a href="http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html">W3C Web Component</a> » apporte des réponses à cette question particulière. Le <a href="http://x-tags.org/">projet X-Tag</a> est un essai de mise en œuvre de cette spécification ; nous vous encourageons à y jeter un coup d'œil.</p> +</div> + +<h3 id="Pourquoi_ne_fonctionne-t-il_pas">Pourquoi ne fonctionne-t-il pas ?</h3> + +<p> </p> + +<p>Avant de commencer, il est important de se rappeler quelque chose de très important à propos de JavaScript : dans un navigateur, c'est une technique peu fiable. Lorsque vous créez des widgets personnalisés, vous êtes obligé de faire appel à JavaScript parce que c'est un fil nécessaire pour tout lier ensemble. Cependant, il existe de nombreux cas dans lesquels JavaScript n'est pas capable de s'exécuter dans le navigateur :</p> + +<ul> + <li>L'utilisateur a désactivé le JavaScript : c'est un cas assez inhabituel, peu de personnes désactivent le JavaScript de nos jours.</li> + <li>Le script ne se charge pas. La chose est très courante, en particulier dans le domaine des mobiles pour lesquels le réseau n'est pas sûr.</li> + <li>Le script est bogué. Il faut toujours prendre en considération cette éventualité.</li> + <li>Le script est en conflit avec un autre script tierce‑partie. Cela peut se produire avec des suites de scripts ou n'importe quel marque page utilisé par l'utilisateur.</li> + <li>Le script est en conflit avec, ou est affecté par un extension de navigateur (comme l'extension « <a href="https://addons.mozilla.org/fr/firefox/addon/noscript/">No script</a> » de Firefox ou « <a href="https://chrome.google.com/webstore/detail/notscripts/odjhifogjcknibkahlpidmdajjpkkcfn" rel="external" title="https://chrome.google.com/webstore/detail/notscripts/odjhifogjcknibkahlpidmdajjpkkcfn">Scripts »</a> de Chrome).</li> + <li>L'utilisateur utilise un navigateur ancien et l'une des fonctions dont vous avez besoin n'est pas prise en charge. Cela se produira fréquemment lorsque vous utiliserez des API de pointe.s.</li> +</ul> + +<p> </p> + +<p> </p> + +<p>En raison de ces aléas, il est vraiment important de considérer avec sérieux ce qui se passe si JavaScript ne fonctionne pas. Traiter en détail cette question est hors de la portée de cet article parce qu'elle est étroitement liée à la façon dont vous voulez rendre votre script générique et réutilisable, mais nous prendrons en considération les bases de ce sujet dans notre exemple.</p> + +<p>Ainsi, si notre code JavaScript ne s'exécute pas, nous reviendrons à l'affichage d'un élément {{HTMLElement("select")}} standard. Pour y parvenir, nous avons besoin de deux choses.</p> + +<p>Tout d'abord, nous devons ajouter un élément {{HTMLElement("select")}} régulier avant chaque utilisation de notre widget personnalisé. Ceci est également nécessaire pour pouvoir envoyer les données de notre widget personnalisé avec le reste de nos données du formulaire ; nous reviendrons sur ce point plus tard.</p> + +<p> </p> + +<pre class="brush: html"><body class="no-widget"> + <form> + <select name="myFruit"> + <option>Cerise</option> + <option>Citron</option> + <option>Banane</option> + <option>Fraise</option> + <option>Pomme</option> + </select> + + <div class="select"> + <span class="value">Cerise</span> + <ul class="optList hidden"> + <li class="option">Cerise</li> + <li class="option">Citron</li> + <li class="option">Banane</li> + <li class="option">Fraise</li> + <li class="option">Pomme</li> + </ul> + </div> + </form> + +</body></pre> + +<p> </p> + +<p>Deuxièmement, nous avons besoin de deux nouvelles classes pour nous permettre de cacher l'élément qui ne sert pas (c'est-à-dire l'élément{{HTMLElement("select")}} « réel » si notre script ne fonctionne pas, ou le widget personnalisé s'il fonctionne). Notez que par défaut, le code HTML cache le widget personnalisé.</p> + +<pre class="brush: css">.widget select, +.no-widget .select { + /* Ce sélecteur CSS dit fondamentalement : + - soit la classe body est "widget" et donc l'élément {{HTMLElement("select")}} réel sera caché + - soit la classe body n'a pas changé, elle est toujours "no-widget", + et donc les éléments, dont la classe est « select », doivent être cachés */ + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +}</pre> + +<p> </p> + +<p>Maintenant nous avons juste besoin d'un commutateur JavaScript pour déterminer si le script est en cours d'exécution ou non. Cette bascule est très simple : si au moment du chargement de la page notre script est en cours d'exécution, il supprime la classe no-widget et ajoute la classe widget, échangeant ainsi la visibilité de l'élément {{HTMLElement("select")}} et du widget personnalisé.</p> + +<p> </p> + +<p> </p> + +<pre class="brush: js">window.addEventListener("load", function () { + document.body.classList.remove("no-widget"); + document.body.classList.add("widget"); +});</pre> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Sans JavaScript</th> + <th scope="col" style="text-align: center;">Avec JavaScript</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("No_JS",120,130, "", "Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Exemple_2")}}</td> + <td>{{EmbedLiveSample("JS",120,130, "", "Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Exemple_2")}}</td> + </tr> + <tr> + <td colspan="2" style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_2" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_2">Testez le code source</a></td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Note :</strong> Si vous voulez vraiment rendre votre code générique et réutilisable, au lieu de faire un changement de classe, il est préférable d'ajouter la classe widget pour cacher les éléments {{HTMLElement("select")}} et d'ajouter dynamiquement l'arbre DOM représentant le widget personnalisé après chaque élément {{HTMLElement("select")}} dans la page.</p> +</div> + +<h3 id="Rendre_le_travail_plus_facile">Rendre le travail plus facile</h3> + +<p> </p> + +<p>Dans le code que nous sommes sur le point de construire, nous utiliserons l'API standard DOM pour faire tout le travail dont nous avons besoin. Cependant, bien que la prise en charge de l'API DOM se soit améliorée dans les navigateurs, il y a toujours des problèmes avec les anciens navigateurs (surtout avec le bon vieux navigateur Internet Explorer).</p> + +<p>Si vous voulez éviter les problèmes avec les navigateurs anciens, il y a deux façons de le faire : en utilisant un framework dédié tel que jQuery, $dom, prototype, Dojo, YUI ou similaire, ou bien en remplissant la fonctionnalité manquante que vous voulez utiliser (ce qui peut facilement être fait par un chargement conditionnel, avec la bibliothèque yepnope par exemple).</p> + +<p>Les fonctionnalités que nous prévoyons d'utiliser sont les suivantes (classées de la plus risquée à la plus sûre) :</p> + +<ol> + <li>{{domxref("element.classList","classList")}}</li> + <li>{{domxref("EventTarget.addEventListener","addEventListener")}}</li> + <li><code><a href="/fr/docs/JavaScript/Reference/Global_Objects/Array/forEach" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach">forEach</a></code> (ce n'est pas du DOM mais du JavaScript moderne)</li> + <li>{{domxref("element.querySelector","querySelector")}} et {{domxref("element.querySelectorAll","querySelectorAll")}}</li> +</ol> + +<p>Au-delà de la disponibilité de ces fonctionnalités spécifiques, il reste encore un problème avant de commencer. L'objet retourné par la fonction {{domxref("element.querySelectorAll","querySelectorAll()")}} est une {{domxref("NodeList")}} plutôt qu'un <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array">Array</a></code>. C'est important, car les objets <code>Array</code> acceptent la fonction <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach">forEach</a></code>, mais {{domxref("NodeList")}} ne le fait pas. Comme {{domxref("NodeList")}} ressemble vraiment à un <code>Array</code> et que <code>forEach</code> est d'utilisation si commode, nous pouvons facilement ajouter la prise en charge de <code>forEach à</code> {{domxref("NodeList")}} pour nous faciliter la vie, comme ceci :</p> + +<pre class="brush: js">NodeList.prototype.forEach = function (callback) { + Array.prototype.forEach.call(this, callback); +}</pre> + +<p>On ne plaisantait pas quand on a dit que c'était facile à faire.</p> + +<h3 id="Construction_des_fonctions_de_rappel_d'événements">Construction des fonctions de rappel d'événements</h3> + +<p>Les fondations sont prêtes, nous pouvons maintenant commencer à définir toutes les fonctions à utiliser chaque fois que l'utilisateur interagit avec notre widget.</p> + +<pre class="brush: js">// Cette fonction est utilisée chaque fois que nous voulons désactiver un +// widget personnalisé. Elle prend un paramètre +// select : le nœud DOM avec la classe select à désactiver +function deactivateSelect(select) { + + // Si le widget n'est pas actif, il n'y a rien à faire + if (!select.classList.contains('active')) return; + + // Nous devons obtenir la liste des options pour le widget personnalisé + var optList = select.querySelector('.optList'); + + // Nous cachons la liste des options + optList.classList.add('hidden'); + + // et nous désactivons le widget personnalisé lui-même + select.classList.remove('active'); +} + +// Cette fonction sera utilisée chaque fois que l'utilisateur veut (des)activer le widget +// Elle prend deux paramètres : +// select : le nœud DOM de la classe `select` à activer +// selectList : la liste de tous les nœuds DOM de la classe `select` +function activeSelect(select, selectList) { + + // Si le widget est déjà actif il n'y a rien à faire + if (select.classList.contains('active')) return; + + // Nous devons désactiver tous les widgets personnalisés + // comme la fonction deactivateSelect remplit toutes les fonctionnalités de la + // fonction de rappel forEach, nous l'utilisons directement sans utiliser + // une fonction anonyme intermédiaire. + selectList.forEach(deactivateSelect); + + // Et nous activons l'état du widget donné + select.classList.add('active'); +} + +// Cette fonction sera utilisée chaque fois que l'utilisateur veut enrouler/dérouler la +// liste des options +// Elle prend un paramètre : +// select : le nœud DOM de la liste à basculer +function toggleOptList(select) { + + // La liste est prise à partir du widget + var optList = select.querySelector('.optList'); + + // Nous changeons la classe de la liste pour l'enrouler/dérouler + optList.classList.toggle('hidden'); +} + +// Cett fonction sera utilisée chaque fois qu'il faut mettre en surbrillance +// une option. Elle prend deux paramètres : +// select : le nœud DOM de la classe `select` +// contenant l'option à mettre en surbrillance +// option : le nœud DOM de la classe `option` à mettre en surbrillance +function highlightOption(select, option) { + + // Obtenir la liste de toutes les options disponibles pour l'élémént sélectionné + var optionList = select.querySelectorAll('.option'); + + // Supprimer la surbrillance pour toutes les options + optionList.forEach(function (other) { + other.classList.remove('highlight'); + }); + + // Mettre en surbrillance l'option correcte + option.classList.add('highlight'); +};</pre> + +<p>C'est tout ce dont on a besoin pour gérer les différents états du widget personnalisé.</p> + +<p>Ensuite, nous assujettissons ces fonctions aux événement appropriés :</p> + +<pre class="brush: js">// Nous lions le widget aux événements dès le chargement du document +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + // Chaque widget personnalisé doit être initialisé + selectList.forEach(function (select) { + + // de même que tous les éléments `option` + var optionList = select.querySelectorAll('.option'); + + // Chaque fois que l'utilisateur passe le pointeur de souris + // sur une option, nous mettons en surbrillance la dite option + + optionList.forEach(function (option) { + option.addEventListener('mouseover', function () { + // Note : les variables `select` et `option` sont des "closures" + // disponibles dans la portée de notre appel de fonction. + highlightOption(select, option); + }); + }); + + // Chaque fois que l'utilisateur clique sur un élément personnalisé + select.addEventListener('click', function (event) { + // Note : la variable `select` est une "closure" + // available dans la portée de notre appel de fonction. + + // Nous basculons la visibilité de la liste des options + toggleOptList(select); + }); + + // Dans le cas où le widget obtient le focus + // Le widget obtient le focus chaque fois que l'utilisateur clique dessus + // ou presse la touche Tab pour avoir accès au widget + select.addEventListener('focus', function (event) { + // Note : les variable `select` et `selectList` sont des "closures" + // disponibles dans la portée de notre appel de fonction. + + // Nous activons le widget + activeSelect(select, selectList); + }); + + // Dans le cas où le widget perd le focus + select.addEventListener('blur', function (event) { + // Note : la variable `select` est une "closure" + // disponible dans la portée de notre appel de fonction. + + // Nous désactivons le widget + deactivateSelect(select); + }); + }); +});</pre> + +<p>A ce stade, notre widget change d'état comme nous l'avons conçu, mais sa valeur n'est pas encore mise à jour. On s'en occupera après.</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Exemple en direct</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Example_3")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Example_3" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_3">Revoir le code source</a></td> + </tr> + </tbody> +</table> + +<h3 id="Gérer_la_valeur_du_widget">Gérer la valeur du widget</h3> + +<p> </p> + +<p>Maintenant que notre widget fonctionne, nous devons ajouter du code pour mettre à jour la valeur en fonction des entrées utilisateur et envoyer cette valeur avec les données du formulaire.</p> + +<p>La façon la plus simple de le faire est d'utiliser un widget natif sous‑jacent. Un tel widget gardera une trace de la valeur avec tous les contrôles intégrés fournis par le navigateur, et la valeur sera envoyée comme d'habitude lorsque le formulaire sera soumis. Il ne sert à rien de réinventer la roue alors que tout cela peut être fait pour nous.</p> + +<p>Comme nous l'avons vu précédemment, nous utilisons déjà un widget de sélection natif comme solution de repli pour des raisons d'accessibilité ; nous pouvons simplement synchroniser sa valeur avec celle de notre widget personnalisé :</p> + +<pre class="brush: js">// Cette fonction met à jour la valeur affichée et la synchronise avec celle +// du widget natif. Elle prend deux paramètres : +// select : le nœud DOM de la classe `select` contenant la valuer à mettre à jour +// index : l'index de la valeur choisie +function updateValue(select, index) { + // Nous devons obtenir le widget natif correspondant au widget personnalisé + // Dans notre exemple, le widget natif est un parent du widget personnalisé + var nativeWidget = select.previousElementSibling; + + // Nou devons aussi obtenir la valeur de remplacement du widget personnalisé + var value = select.querySelector('.value'); + + // Et nous avons besoin de toute la liste des options + var optionList = select.querySelectorAll('.option'); + + // Nous définissons l'index choisi à l'index du choix + nativeWidget.selectedIndex = index; + + // Nous mettons à jour la valeur de remplacement en accord + value.innerHTML = optionList[index].innerHTML; + + // Et nous mettons en surbrillance l'option correspondante du widget personnalisé + highlightOption(select, optionList[index]); +}; + +// Cette fonction renvoie l'index courant dans le widget natif +// Elle prend un paramètre : +// select : le nœud DOM avec la classe `select` relative au widget natif +function getIndex(select) { + // Nous avons besoin d'avoir accès au widget natif pour le widget personnalisé + // Dans notre exemple, le widget natif est un parent du widget personnalisé + var nativeWidget = select.previousElementSibling; + + return nativeWidget.selectedIndex; +};</pre> + +<p>Avec ces deux fonctions, nous pouvons lier les widgets natifs avec les personnalisés :</p> + +<pre class="brush: js">// Nous lions le widget aux événements dès le chargement du document +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + // Chaque widget personnalisé doit être initialisé + selectList.forEach(function (select) { + var optionList = select.querySelectorAll('.option'), + selectedIndex = getIndex(select); + + // Nous rendons le widget personnalisé capable d'avoir le focus + select.tabIndex = 0; + + // Nous faisons en sorte que le widget natif ne puisse plus avoir le focus + select.previousElementSibling.tabIndex = -1; + + // Nous nous assurons que la valeur sélectionnée par défaut est bien affichée + updateValue(select, selectedIndex); + + // Chaque fois que l'utilisateur clique sur une option, nous mettons à + // jour la valeur en accord + optionList.forEach(function (option, index) { + option.addEventListener('click', function (event) { + updateValue(select, index); + }); + }); + + // Chaque fois que l'utilisateur utilise le clavier sur un widget + // avec focus, les valeurs sont mises à jour en accord + + select.addEventListener('keyup', function (event) { + var length = optionList.length, + index = getIndex(select); + + // Quand l'utilisateur presse ⇓, nous allons à l'option suivante + if (event.keyCode === 40 && index < length - 1) { index++; } + + // Quand l'utilisateur presse ⇑, nous sautons à l'option suivante + if (event.keyCode === 38 && index > 0) { index--; } + + updateValue(select, index); + }); + }); +});</pre> + +<p>Dans le code ci-dessus, il faut noter l'utilisation de la propriété <code><a href="/en-US/docs/Web/API/HTMLElement/tabIndex" title="/en-US/docs/Web/API/HTMLElement/tabIndex">tabIndex</a></code>. Utiliser cette propriété est nécessaire pour être sûr que le widget natif n'obtiendra jamais le focus et que le widget personnalisé l'obtiendra quand l'utilisateur utilise le clavier ou la souris.</p> + +<p>Et voilà, nous avons terminé ! Voici le résultat :</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Exemple en direct</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Example_4")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Example_4" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_3">Revoir le code source</a></td> + </tr> + </tbody> +</table> + +<p>Mais attendez, avons‑nous vraiment terminé ?</p> + +<h2 id="Le_rendre_«_accessible_»">Le rendre « accessible »</h2> + +<p> </p> + +<p>Nous venons de faire quelque chose qui fonctionne, même si nous sommes loin d'avoir une boîte de sélection avec toutes les fonctionnalités, elle fonctionne parfaitement. Mais ce que nous avons fait n'est rien de plus que de jouer avec les DOM. Elle n'a pas de sémantique réelle, et même si elle ressemble à une boîte de sélection, du point de vue du navigateur, ce n'en est pas une, de sorte que les technologies d'assistance ne pourront pas comprendre que c'est une boîte de sélection. Bref, cette jolie nouvelle boîte de sélection n'est pas accessible !</p> + +<p>Heureusement, il existe une solution et elle s'appelle <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a>. ARIA signifie « Accessible Rich Internet Application » et c'est une<a href="http://www.w3.org/TR/wai-aria/" rel="external" title="http://www.w3.org/TR/wai-aria/"> norme W3C </a>spécialement conçue pour ce que nous faisons ici : rendre accessibles les applications web et les widgets personnalisés. Il s'agit essentiellement d'un ensemble d'attributs qui étendent le HTML afin que nous puissions mieux décrire les rôles, les états et les propriétés comme si l'élément que nous venons de concevoir était l'élément natif pour lequel il essaie de passer. L'utilisation de ces attributs est très simple, alors faisons-le.</p> + +<h3 id="L'attribut_role">L'attribut <code>role</code></h3> + +<p>L'attribut clé utilisé par <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a> est l'attribut <a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques"><code>role</code></a>. L'attribut <a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques"><code>role </code></a> accepte une valeur qui définit à quoi sert un élément. Chaque rôle définit ses propres exigences et comportements. Dans notre exemple, nous utiliserons le rôle de <code><a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role">listbox</a></code>. C'est un « rôle composite », ce qui signifie que les éléments ayant ce rôle s'attendent à avoir des enfants, chacun avec un rôle spécifique (dans ce cas, au moins un enfant avec le rôle <code>option</code>).</p> + +<p>Il faut aussi noter qu'ARIA définit les rôles appliqués par défaut aux balises HTML standard. Par exemple, l'élément {{HTMLElement("table")}} correspond au rôle <code>grid</code>, et l'élément {{HTMLElement("ul")}} correspond au rôle <code>list</code>. Comme nous utilisons un élément {{HTMLElement("ul")}}, nous voulons nous assurer que le rôle <code>listbox</code> de notre widget remplacera le rôle <code>list</code> de l'élément {{HTMLElement("ul")}}. À cette fin, nous utiliserons le rôle <code>presentation</code>. Ce rôle est conçu pour nous permettre d'indiquer qu'un élément n'a pas de signification particulière, et est utilisé uniquement pour présenter de l'information. Nous l'appliquerons à notre élément {{HTMLElement("ul")}}.</p> + +<p>Pour prendre en charge le rôle <code>listbos</code>, nous n'avons qu'à mettre à jour notre HTML comme ceci :</p> + +<pre class="brush: html"><!-- Nous ajoutons le role="listbox" en attribut de l'élément de tête --> +<div class="select" role="listbox"> + <span class="value">Cherry</span> + <!-- Nous ajoutons aussi le role="presentation" à l'élément ul --> + <ul class="optList" role="presentation"> + <!-- et le rôle="option" en attribut de tous les éléments li --> + <li role="option" class="option">Cherry</li> + <li role="option" class="option">Lemon</li> + <li role="option" class="option">Banana</li> + <li role="option" class="option">Strawberry</li> + <li role="option" class="option">Apple</li> + </ul> +</div></pre> + +<div class="note"> +<p><strong>Note :</strong> Inclure à la fois l'attribut <code>role</code> et l'attribut <code>class</code> n'est nécessaire que si vous souhaitez prendre en charge les navigateurs anciens qui n'acceptent pas les <a href="/en-US/docs/CSS/Attribute_selectors" title="/en-US/docs/CSS/Attribute_selectors">selecteurs d'attribut CSS</a>.</p> +</div> + +<h3 id="L'attribut_aria-selected">L'attribut <code>aria-selected</code></h3> + +<p>Utiliser l'attribut <code>role</code> ne suffit pas. <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a> fournit également de nombreux états et attributs de propriété. Plus vous les utiliserez, mieux votre widget sera compris par les techniques d'assistance. Dans notre cas, nous limiterons notre utilisation à un seul attribut : <code>aria-selected</code>.</p> + +<p>L'attribut <code>aria-selected</code> s'utilise pour marquer l'option actuellement sélectionnée ; ceci permet aux techniques d'assistance d'informer l'utilisateur quelle est la sélection en cours. Nous l'utiliserons dynamiquement avec JavaScript pour marquer l'option sélectionnée chaque fois que l'utilisateur en choisit une. Pour cela, nous devons réviser la fonction <code>updateValue()</code> :</p> + +<pre class="brush: js">function updateValue(select, index) { + var nativeWidget = select.previousElementSibling; + var value = select.querySelector('.value'); + var optionList = select.querySelectorAll('.option'); + + // Nous nous assurons qu'aucune option n'est sélectionnée + optionList.forEach(function (other) { + other.setAttribute('aria-selected', 'false'); + }); + + // Nous nous assurons que l'option choisie est sélectionnée + optionList[index].setAttribute('aria-selected', 'true'); + + nativeWidget.selectedIndex = index; + value.innerHTML = optionList[index].innerHTML; + highlightOption(select, optionList[index]); +};</pre> + +<p>Voici le résultat final de toutes ces modifications (vous obtiendrez un meilleur ressenti en les testant avec une technique d'assistance comme <a href="http://www.nvda-project.org/" rel="external" title="http://www.nvda-project.org/">NVDA</a> ou <a href="http://www.apple.com/accessibility/voiceover/" rel="external" title="http://www.apple.com/accessibility/voiceover/">VoiceOver</a>) :</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Exemple en direct</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Example_5")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Example_5" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_3">Revoir le code source</a></td> + </tr> + </tbody> +</table> + +<h2 id="Conclusion">Conclusion</h2> + +<p>Nous venons de voir les bases pour la construction d'un widget de formulaire personnalisé, mais comme vous avez pu le voir, ce n'est pas facile à faire, et il est souvent préférable et plus facile de s'appuyer sur des bibliothèques tierces au lieu de les coder vous-même (sauf, bien sûr, si vous souhaitez bâtir une telle bibliothèque).</p> + +<p>Voici quelques bibliothèques à prendre en considération avant de coder les vôtres :</p> + +<ul> + <li><a href="http://jqueryui.com/" rel="external" title="http://jqueryui.com/">jQuery UI</a></li> + <li><a href="https://github.com/marghoobsuleman/ms-Dropdown" rel="external" title="https://github.com/marghoobsuleman/ms-Dropdown">msDropDown</a></li> + <li><a href="http://www.emblematiq.com/lab/niceforms/" rel="external" title="http://www.emblematiq.com/lab/niceforms/">Nice Forms</a></li> + <li><a href="https://www.google.fr/search?q=HTML+custom+form+controls&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:fr:official&client=firefox-a" rel="external" title="https://www.google.fr/search?q=HTML+custom+form+controls&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:fr:official&client=firefox-a">et beaucoup d'autres…</a></li> +</ul> + +<p>Si vous voulez aller plus loin, le code de cet exemple mérite quelques amélioration avant de devenir générique et réutilisable. C'est un exercice que vous pouvez essayer de faire. Deux conseils pour vous aider : le premier argument pour toutes nos fonctions est le même, ce qui signifie que ces fonctions ont besoin du même contexte. Il serait avisé de construire un objet pour partager ce contexte. En outre, vous devrez éprouver ses fonctionnalités, c'est-à-dire qu'il doit pouvoir fonctionner avec les divers navigateurs dont la compatibilité avec les normes Web qu'ils utilisent varie. Amusez-vous bien !</p> + +<p>{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Validation_donnees_formulaire", "Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript", "Web/Guide/HTML/Formulaires")}}</p> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML">Mon premier formulaire HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML"><span>Comment structurer un formulaire HTML</span></a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">Les widgets natifs pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets personnalisés pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">Mise en forme des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">Mise en forme avancée des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Table de compatibilité des propriétés pour les widgets de formulaire</a></li> +</ul> diff --git a/files/fr/web/guide/html/formulaires/comment_structurer_un_formulaire_html/exemple/index.html b/files/fr/web/guide/html/formulaires/comment_structurer_un_formulaire_html/exemple/index.html new file mode 100644 index 0000000000..91cd643bd1 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/comment_structurer_un_formulaire_html/exemple/index.html @@ -0,0 +1,166 @@ +--- +title: Exemple +slug: Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML/Exemple +translation_of: Learn/Forms/How_to_structure_a_web_form/Example +--- +<p>Ceci est un exemple de formulaire de paiement basique extrait de l'article <a href="/fr/docs/HTML/Formulaires/Comment_structurer_un_formulaire_HTML" title="/fr/docs/HTML/Formulaires/Comment_structurer_un_formulaire_HTML">Comment structurer un formulaire HTML</a>.</p> + +<h2 id="Un_formulaire_de_paiement" name="Un_formulaire_de_paiement">Un formulaire de paiement</h2> + +<h3 id="Contenu_HTML">Contenu HTML</h3> + +<pre class="brush: html"><form> + <h1>Formulaire de paiement</h1> + <p>Les champs obligatoires sont suivis par <strong><abbr title="required">*</abbr></strong>.</p> + <section> + <h2>Informations de contact</h2> + <fieldset> + <legend>Qualité</legend> + <ul> + <li> + <label for="title_1"> + <input type="radio" id="title_1" name="title" value="M." > + Monsieur + </label> + </li> + <li> + <label for="title_2"> + <input type="radio" id="title_2" name="title" value="Mme."> + Madame + </label> + </li> + </ul> + </fieldset> + <p> + <label for="name"> + <span>Nom :</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="text" id="name" name="username"> + </p> + <p> + <label for="mail"> + <span>e-mail :</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="email" id="mail" name="usermail"> + </p> + <p> + <label for="password"> + <span>Mot de passe :</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="password" id="pwd" name="password"> + </p> + </section> + <section> + <h2>Informations de paiement</h2> + <p> + <label for="card"> + <span>Type de carte :</span> + </label> + <select id="card" name="usercard"> + <option value="visa">Visa</option> + <option value="mc">Mastercard</option> + <option value="amex">American Express</option> + </select> + </p> + <p> + <label for="number"> + <span>Numéro :</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="text" id="number" name="cardnumber"> + </p> + <p> + <label for="date"> + <span>Validité :</span> + <strong><abbr title="required">*</abbr></strong> + <em>format mm/aa</em> + </label> + <input type="text" id="date" name="expiration"> + </p> + </section> + <section> + <p> <button type="submit">Valider le paiement</button> </p> + </section> + </form></pre> + +<h3 id="Contenu_CSS">Contenu CSS</h3> + +<pre class="brush: css"> h1 { + margin-top: 0; + } + + ul { + margin: 0; + padding: 0; + list-style: none; + } + + form { + margin: 0 auto; + width: 450px; + padding: 1em; + border: 1px solid #CCC; + border-radius: 1em; + } + + div+div { + margin-top: 1em; + } + + label span { + display: inline-block; + width: 120px; + text-align: right; + } + + input, textarea { + font: 1em sans-serif; + width: 250px; + box-sizing: border-box; + border: 1px solid #999; + } + + input[type=checkbox], input[type=radio] { + width: auto; + border: none; + } + + input:focus, textarea:focus { + border-color: #000; + } + + textarea { + vertical-align: top; + height: 5em; + resize: vertical; + } + + fieldset { + width: 250px; + box-sizing: border-box; + margin-left: 146px; + border: 1px solid #999; + } + + button { + margin: 20px 0 0 124px; + } + + label { + position: relative; + } + + label em { + position: absolute; + right: 5px; + top: 20px; + }</pre> + +<h3 id="Résultat">Résultat</h3> + +<p>{{ EmbedLiveSample("Un_formulaire_de_paiement", "100%", "620") }}</p> + +<p> </p> diff --git a/files/fr/web/guide/html/formulaires/comment_structurer_un_formulaire_html/index.html b/files/fr/web/guide/html/formulaires/comment_structurer_un_formulaire_html/index.html new file mode 100644 index 0000000000..f7d2e7db7d --- /dev/null +++ b/files/fr/web/guide/html/formulaires/comment_structurer_un_formulaire_html/index.html @@ -0,0 +1,310 @@ +--- +title: Comment structurer un formulaire HTML +slug: Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML +tags: + - Apprentissage + - Débutant + - Exemple + - Formulaires + - Guide + - HTML + - Structure + - Web +translation_of: Learn/Forms/How_to_structure_a_web_form +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML", "Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs", "Web/Guide/HTML/Formulaires")}}</div> + +<p class="summary">Les bases vues, nous examinons maintenant plus en détail les éléments utilisés pour structurer et donner un sens aux différentes parties d'un formulaire.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td>Notions concernant les ordinateurs et les <a class="new" href="https://developer.mozilla.org/fr/docs/Learn/HTML/Introduction_to_HTML" rel="nofollow">connaissances de base du HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td>Comprendre comment structurer les formulaires HTML et leur adjoindre la sémantique pour qu'ils soient utilisables et accessibles.</td> + </tr> + </tbody> +</table> + +<p>La souplesse des formulaires HTML fait d'eux une des structures les plus complexes en <a href="/fr/docs/HTML" title="/en-US/docs/HTML">HTML</a>. vous pouvez construire n'importe quel type de formulaire basique en utilisant les éléments et attributs qui leur sont dédiés. En utilisant une architecture correcte lors de la construction d'un formulaire, vous serez sûrs que le formulaire est à la fois utilisable et <a href="/fr/docs/MDN/Doc_status/Accessibility">accessible</a>.</p> + +<h2 id="L'élément_<form>">L'élément <form></h2> + +<p>L'élément {{HTMLElement("form")}} définit conventionnellement un formulaire et des attributs qui déterminent le comportement du‑dit formulaire. Chaque fois que vous voulez créer un formulaire HTML, vous devez le débuter par cet élément et mettre tout son contenu à l'intérieur. De nombreuses techniques d'assistance ou greffons de navigateur peuvent détecter les éléments {{HTMLElement("form")}} et implémenter des accroches spéciales pour les rendre plus faciles à utiliser.</p> + +<p>Nous l'avons déjà rencontré dans l'article précédent.</p> + +<div class="note"><strong>Note :</strong> Il est strictement interdit d'imbriquer un formulaire dans un autre formulaire. L'imbrication peut conduire à des comportements imprévisibles selon le navigateur utilisé.</div> + +<p>Notez qu'il est toujours possible d'utiliser un widget de formulaire en dehors d'un élément {{HTMLElement("form")}} mais si vous le faites, ce widget de formulaire n'a rien à voir avec un formulaire. De tels widgets peuvent être utilisés en dehors d'un formulaire, mais alors vous devriez avoir un plan spécial pour de tels widgets, puisqu'ils ne feront rien tout seuls. Vous devrez personnaliser leur comportement avec JavaScript.</p> + +<div class="note"> +<p><strong>Note</strong>: HTML5 introduit l'attribut <code>form</code> dans les éléments form du HTML. Il devrait vous permettre de lier explicitement un élément avec un formulaire même s'il n'est pas inclus dans un {{ HTMLElement("form") }}. Malheureusement, pour l'instant, l'implémentation de cette fonctionnalité dans les navigateurs n'est pas encore assez fiable.</p> +</div> + +<h2 id="Les_éléments_<fieldset>_et_<legend>">Les éléments <fieldset> et <legend></h2> + +<p>L'élément {{HTMLElement("fieldset")}} est un moyen pratique de créer des groupes de widgets qui partagent le même but, pour le style et la sémantique. Vous pouvez étiqueter un {{HTMLElement("fieldset")}} en incluant un élément {{HTMLElement("legend")}} juste en dessous de la balise d'ouverture <fieldset>. Le contenu textuel de l'élément {{HTMLElement("legend")}} décrit formellement le but de l'élément {{HTMLElement("fieldset")}} inclus à l'intérieur.</p> + +<p>De nombreuses technologies d'assistance utiliseront l'élément {{HTMLElement("legend")}} comme s'il faisait partie de l'étiquette de chaque widget à l'intérieur de l'élément {{HTMLElement("fieldset")}} correspondant. Par exemple, certains lecteurs d'écran comme <a href="http://www.freedomscientific.com/products/fs/jaws-product-page.asp" rel="external" title="http://www.freedomscientific.com/products/fs/jaws-product-page.asp">Jaws</a> ou <a href="http://www.nvda-project.org/" rel="external" title="http://www.nvda-project.org/">NVDA</a> énonceront le contenu de la légende avant d'indiquer l'étiquette de chaque widget.</p> + +<p>Voici un petit exemple :</p> + +<pre class="brush:html; line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>form</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>fieldset</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>legend</span><span class="punctuation token">>Taille du jus de fruits</span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>legend</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>radio<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>size<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>size_1<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>small<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>size_1<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Petite<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>radio<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>size<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>size_2<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>medium<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>size_2<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Moyen<span class="tag token"><span class="tag token"><span class="punctuation token">ne</</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>radio<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>size<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>size_3<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>large<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>size_3<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Grand<span class="tag token"><span class="tag token"><span class="punctuation token">e</</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>fieldset</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>form</span><span class="punctuation token">></span></span></code></pre> + +<div class="note"> +<p><strong>Note </strong>: Vous trouverez cet exemple dans <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/fieldset-legend.html">fieldset-legend.html</a> (voir <a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/fieldset-legend.html">directement aussi</a>).</p> +</div> + +<p>En lisant le formulaire ci-dessus, un lecteur d'écran dira « Taille du jus de fruit : petit » pour le premier widget, « Taille du jus de fruit : moyenne » pour le second, et « Taille du jus de fruit : grande » pour le troisième.</p> + +<p>Le scenario d'utilisation du lecteur dans cet exemple est l'un des plus importants. Chaque fois que vous avez un ensemble de boutons radio, vous devez les imbriquer dans un élément {{HTMLElement("fieldset")}}. Il y a d'autres scenarii d'utilisation, et en général l'élément {{HTMLElement("fieldset")}} peut aussi être utilisé pour partager un formulaire. Idéalement, les formulaires longs doivent être éclatés sur plusieurs pages, mais si un formulaire long doit être sur une page unique, le fait de placer les différentes sections connexes dans de différents {{HTMLElement("fieldset")}} peut en améliorer l'utilisation.</p> + +<p>En raison de son influence sur les techniques d'assistance, l'élément {{HTMLElement("fieldset")}} est l'un des éléments clés pour la création de formulaires accessibles ; cependant, il vous appartient de ne pas en abuser. Si possible, chaque fois que vous créez un formulaire, essayez d'<a href="https://www.nvaccess.org/download/">écouter comment un lecteur d'écran</a> l'interprète. Si cela ne paraît pas naturel, essayez d'améliorer la structure du formulaire.</p> + +<h2 id="L'élément_<label>">L'élément <label></h2> + +<p>Comme nous l'avons vu dans l'article précédent, l'élément {{HTMLElement("label")}} est le moyen naturel de définir une étiquette pour un widget de formulaire HTML. C'est l'élément le plus important si vous voulez créer des formulaires accessibles — lorsqu'ils sont correctement implémentés, les lecteurs d'écran énonceront l'étiquette d'un élément de formulaire selon toutes les instructions associées. Prenons cet exemple, que nous avons vu dans l'article précédent :</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>name<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Nom :<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>text<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>name<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>user_name<span class="punctuation token">"</span></span><span class="punctuation token">></span></span></code></pre> + +<p>Avec un élément <code><label></code> correctement associé à <code><input></code> par l'intermédiaire respectivement des attributs <code>for</code> et <code>id</code> (l'attribut <code>for</code> de <label> référence l'attibut <code>id</code> du widget correspondant), un lecteur d'écran lira et dira quelque chose comme « Nom, texte indiqué ».</p> + +<p>Si l'étiquette n'est pas correctement paramétrée, le lecteur d'écran dira quelque chose comme « Texte édité vierge », ce qui n'est pas utile du tout.</p> + +<p>Notez qu'un widget peut être incorporé dans son élément {{HTMLElement("label")}}, ainsi :</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>name<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + Nom : <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>text<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>name<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>user_name<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span></code></pre> + +<p>Toutefois, même dans ce cas, il est considéré de bonne pratique de définir l'attribut <code>for</code> parce que certaines techniques d'assistance ne font pas implicitement le lien entre les étiquettes et les widgets.</p> + +<h3 id="Les_étiquettes_peuvent_être_cliquées_aussi_!">Les étiquettes peuvent être cliquées, aussi !</h3> + +<p>Autre avantage de bien configurer les étiquettes : vous pouvez cliquer sur l'étiquette pour activer le widget correspondant, dans tous les navigateurs. Utile, par exemple, pour des entrées de texte : vous pouvez cliquer sur l'étiquette ou la zone de texte pour y obtenir le curseur, mais c'est encore plus utile pour les boutons radio et les cases à cocher — la surface active au clic pour une telle commande peut être très réduite, il est donc utile de l'agrandir autant que possible.</p> + +<p>Par exemple :</p> + +<pre class="brush:html; line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>form</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>taste_1<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>J'aime les cerises<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>checkbox<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>taste_1<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>taste_cherry<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>1<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>taste_2<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>J'aime les bananes<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>checkbox<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>taste_2<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>taste_banana<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>2<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>form</span><span class="punctuation token">></span></span></code></pre> + +<div class="note"> +<p><strong>Note </strong>: Vous trouverez cet exemple dans <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/checkbox-label.html">checkbox-label.html</a> (à voir <a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/checkbox-label.html">directement aussi</a>).</p> +</div> + +<h3 id="Étiquettes_multiples">Étiquettes multiples</h3> + +<p>En fait, il est possible d'associer plusieurs étiquettes à un seul widget, mais ce n'est pas une bonne idée car certaines techniques d'assistance peuvent éprouver du trouble pour leur gestion. Dans le cas d'étiquettes multiples, vous devez incorporer le widget et son étiquette dans un seul élément {{htmlelement("label")}}.</p> + +<p>Considérons cet exemple :</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span>Les champs obligatoires sont suivis de <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>abbr</span> <span class="attr-name token">title</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>required<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>*<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>abbr</span><span class="punctuation token">></span></span>.<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + +<span class="comment token"><!-- Donc ceci : --></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>username<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Nom :<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>text<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>username<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>username<span class="punctuation token">"</span></span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>abbr</span> <span class="attr-name token">title</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>required<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>*<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>abbr</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>div</span><span class="punctuation token">></span></span> + +<span class="comment token"><!-- sera mieux programmé ainsi : --></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>username<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>span</span><span class="punctuation token">></span></span>Nom :<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>span</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>username<span class="punctuation token">"</span></span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>text<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>username<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>abbr</span> <span class="attr-name token">title</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>required<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>*<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>abbr</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>div</span><span class="punctuation token">></span></span> + +<span class="comment token"><!-- mais ceci est probablement encore meilleur : --></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>username<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Nom :<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>abbr</span> <span class="attr-name token">title</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>required<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>*<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>abbr</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>username<span class="punctuation token">"</span></span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>text<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>username<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>div</span><span class="punctuation token">></span></span></code></pre> + +<p>Le paragraphe du haut définit la règle pour les éléments obligatoires. Ce doit être au début pour s'assurer que les techniques d'assistance telles que les lecteurs d'écran l'afficheront ou le vocaliseront à l'utilisateur avant qu'il ne trouve un élément obligatoire. Ainsi, ils sauront ce que signifie l'astérisque. Un lecteur d'écran mentionnera l'astérisque en disant « astérisque » ou « obligatoire », selon les réglages du lecteur d'écran — dans tous les cas, ce qui sera dit est clairement précisé dans le premier paragraphe.</p> + +<ul> + <li>Dans le premier exemple, l'étiquette n'est pas lue du tout avec l'entrée — vous obtenez simplement « texte édité vierge », puis les étiquettes réelles sont lues séparément. Les multiples éléments <label> embrouillent le lecteur d'écran.</li> + <li>Dans le deuxième exemple, les choses sont un peu plus claires — l'étiquette lue en même temps que l'entrée est « nom astérisque nom éditer texte », et les étiquettes sont toujours lues séparément. Les choses sont encore un peu confuses, mais c'est un peu mieux cette fois parce que l'entrée a une étiquette associée.</li> + <li>Le troisième exemple est meilleur — les véritables étiquettes sont toutes lues ensemble, et l'étiquette énoncée avec l'entrée est « nom astériquer éditer texte ».</li> +</ul> + +<div class="note"> +<p><strong>Note</strong> : Vous pouvez obtenir des résultats légérement différents, selon votre lecteur d'écran. Ce qui précéde a été testé avec VoiceOver (et NVDA se comporte de la même façon). Nous aimerions avoir un retour sur vos expériences également.</p> +</div> + +<div class="note"> +<p><strong>Note</strong> : Vous trouverez cet exemple sur GitHub dans <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/required-labels.html">required-labels.html</a> (à voir <a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/required-labels.html">directement aussi</a>). Ne lancez pas l'exemple avec 2 ou 3 version non mises en commentaires — le lecteur d'écran serait totalement embrouillé s'il y a plusieurs étiquettes ET plusieurs entrées avec le même ID !</p> +</div> + +<h2 id="Structures_HTML_courantes_dans_les_formulaires">Structures HTML courantes dans les formulaires</h2> + +<p>Au-delà des structures propres aux formulaires HTML,rappelons‑nous que les formulaires sont du pur HTML. Vous pouvez donc utiliser toute la puissance du HTML pour structurer un formulaire.</p> + +<p>Comme vous avez pu le voir dans les exemples, il est de pratique courante d'envelopper une étiquette et son widget avec un élément {{HTMLElement("div")}}. Les éléments {{HTMLElement("p")}} sont aussi couramment utilisés, tout comme les listes HTML (ces dernières sont très courantes pour structurer plusieurs cases à cocher ou boutons radio).</p> + +<p>En plus de l'élément {{HTMLElement("fieldset")}}, il est habituel d'utiliser des titres HTML (par exemple {{htmlelement("h1")}}, {{htmlelement("h2")}}) et des sections (par exemple {{htmlelement("section")}}) pour structurer un formulaire complexe.</p> + +<p>Par-dessus tout, il vous appartient de trouver un style où vous vous sentez à l'aise pour coder, et qui se traduit aussi par des formulaires accessibles et utilisables.</p> + +<p>Chaque groupe de fonctionnalités séparées doit être contenu dans un élément {{htmlelement("section")}} et les boutons radio dans un élément {{htmlelement("fieldset")}}.</p> + +<h3 id="Apprentissage_actif_construire_une_structure_de_formulaire">Apprentissage actif : construire une structure de formulaire</h3> + +<p>Mettons ces idées en pratique et construisons une structure de formulaire un peu plus sophistiquée — un formulaire de paiement. Il contiendra un certain nombre de types de widgets que vous ne comprenez pas encore — ne vous inquiétez pas pour l'instant ; vous découvrirez comment ils fonctionnent dans l'article suivant (<a href="/fr/docs/Learn/HTML/Forms/The_native_form_widgets">Les widgets natifs pour formulaire</a>). Pour l'instant, lisez attentivement les descriptions en suivant les instructions ci-dessous et commencez à vous faire une idée des éléments enveloppes que nous utilisons pour structurer le formulaire, et pourquoi.</p> + +<ol start="1" style="list-style-type: decimal;"> + <li>Pour commencer, faites une copie locale de notre <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">fichier modèle vierge</a> et des <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/payment-form.css">CSS pour notre formulaire de paiement </a> dans un nouveau répertoire.</li> + <li>Primo, appliquez les CSS au HTML en ajoutant la ligne suivante dans l'élément {{htmlelement("head")}} du HTML : + <pre class="brush: html line-numbers language-html"><code class="language-html"><link href="payment-form.css" rel="stylesheet"></code></pre> + </li> + <li>Ensuite, commencez le formulaire en ajoutant un élément {{htmlelement("form")}} : + <pre class="brush: html line-numbers language-html"><form> + +</form></pre> + </li> + <li>Entre les balises <code><form></code>, ajoutez un en‑tête et un paragraphe pour informer les utilisateurs comment sont marqués les champs obligatoires : + <pre class="brush: html line-numbers language-html"><code class="language-html"><h1>Formulaire de paiement</h1> +<p>Les champs obligatoires sont suivis par un <strong><abbr title="required">*</abbr></strong>.</p></code></pre> + </li> + <li>Ensuite, nous ajoutons une grande section de code dans le formulaire, sous la précédente. Ici vous verrez que nous enveloppons les champs d'informations de contact dans des éléments {{htmlelement("section")}} distincts. De plus, nous avons un ensemble de deux boutons radio, que nous mettons chacun à l'intérieur de leur propre élément de liste ({{htmlelement("li")}}). Enfin, nous avons deux zones de texte standard {{htmlelement("input")}} et leurs éléments {{htmlelement("label")}} associés, chacun contenu dans un élément {{htmlelement("p")}}, plus une entrée pour le mot de passe. Ajoutez ce code à votre formulaire maintenant : + <pre class="brush: html line-numbers language-html"><code class="language-html"><section> + <h2>Informations de contact</h2> + <fieldset> + <legend>Qualité</legend> + <ul> + <li> + <label for="title_1"> + <input type="radio" id="title_1" name="title" value="M." > + Monsieur + </label> + </li> + <li> + <label for="title_2"> + <input type="radio" id="title_2" name="title" value="Mme."> + Madame + </label> + </li> + </ul> + </fieldset> + <p> + <label for="name"> + <span>Nom : </span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="text" id="name" name="username"> + </p> + <p> + <label for="mail"> + <span>e-mail :</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="email" id="mail" name="usermail"> + </p> + <p> + <label for="pwd"> + <span>Mot de passe :</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="password" id="pwd" name="password"> + </p> +</section></code></pre> + </li> + <li>Nous arrivons maintenant à la deuxième <code><section></code> de notre formulaire — l'information de paiement. Ici nous avons trois widgets distincts avec leur étiquette, chacun contenu dans un paragraphe <code><p></code>. Le premier est un menu déroulant ({{htmlelement("select")}}) pour le choix du type de la carte de crédit. Le deuxième est un élément <code><input></code> de type nombre pour entrer le numéro de la carte de crédit. Le dernier est un élément <code><input></code> de type <code>date</code> pour entrer la date d'expiration de la carte de crédit (il sera accompagné d'un widget dateur pour les navigateurs prenant en charge cette fonctionnalité, et sera un simple champ textuel pour les navigateurs ne la prenant pas en charge). À nouveau, entrez ce qui suit après la section ci‑dessus : + <pre class="brush: html line-numbers language-html"><code class="language-html"> +<section> + <h2>Informations de paiement</h2> + <p> + <label for="card"> + <span>Type de carte :</span> + </label> + <select id="card" name="usercard"> + <option value="visa">Visa</option> + <option value="mc">Mastercard</option> + <option value="amex">American Express</option> + </select> + </p> + <p> + <label for="number"> + <span>Numéro de carte :</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="text" id="number" name="cardnumber"> + </p> + <p> + <label for="date"> + <span>Validité :</span> + <strong><abbr title="required">*</abbr></strong> + <em>format mm/aa</em> + </label> + <input type="text" id="date" name="expiration"> + </p> +</section></code></pre> + </li> + <li>La dernière section est plus simple ; elle ne contient qu'un bouton {{htmlelement("button")}} de type <code>submit</code>, pour adresser les données du formulaire. Ajoutez ceci au bas du formulaire : + <pre class="brush: html line-numbers language-html"><code class="language-html"><p> <button type="submit">Valider le paiement</button> </p></code></pre> + </li> +</ol> + +<p>Vous pouvez voir le formulaire terminé en action ci‑dessous (vous le trouverez aussi sur GitHub — voir la <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/payment-form.html">source</a> payment-form.html et une exécution <a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/payment-form.html">directe</a>):</p> + +<p>{{EmbedLiveSample("Un_formulaire_de_paiement","100%","620", "", "Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML/Exemple")}}</p> + +<h2 id="Résumé">Résumé</h2> + +<p>Nous savons maintenant ce qu'il faut faire pour structurer de manière appropriée un formulaire HTML ; l'article suivant approfondira la mise en œuvre des divers types de widgets pour formulaire pour collecter les informations utilisateur.</p> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li><a href="http://www.alistapart.com/articles/sensibleforms/" rel="external" title="http://www.alistapart.com/articles/sensibleforms/">A List Apart: <em>Sensible Forms: A Form Usability Checklist</em></a></li> +</ul> + +<p>{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML", "Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs", "Web/Guide/HTML/Formulaires")}}</p> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML">Mon premier formulaire HTML</a></li> + <li><span>Comment structurer un formulaire HTML</span></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">Les widgets natifs pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets personnalisés pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">Mise en forme des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">Mise en forme avancée des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Table de compatibilité des propriétés pour les widgets de formulaire</a></li> +</ul> diff --git a/files/fr/web/guide/html/formulaires/envoyer_et_extraire_les_données_des_formulaires/index.html b/files/fr/web/guide/html/formulaires/envoyer_et_extraire_les_données_des_formulaires/index.html new file mode 100644 index 0000000000..bc81996fda --- /dev/null +++ b/files/fr/web/guide/html/formulaires/envoyer_et_extraire_les_données_des_formulaires/index.html @@ -0,0 +1,371 @@ +--- +title: Envoyer et extraire les données des formulaires +slug: Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires +tags: + - Débutant + - En-têtes + - Fichier + - Formulaire + - Guide + - HTML + - HTTP + - Sécurité + - Web +translation_of: Learn/Forms/Sending_and_retrieving_form_data +--- +<div>{{learnSidebar}}{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs", "Web/Guide/HTML/Formulaires/Validation_donnees_formulaire", "Web/Guide/HTML/Formulaires")}}</div> + +<p class="summary">Cet article examine ce qui arrive quand un utilisateur soumet un formulaire — où les données vont-elles et comment les gère-t-on une fois à destination ? Nous examinerons aussi quelques problèmes de sécurité associés à l'envoi des données d'un formulaire.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td>Notions concernant les ordinateurs, <a class="new" href="https://developer.mozilla.org/fr/docs/Learn/HTML/Introduction_to_HTML" rel="nofollow">compréhension du HTML</a>, et<a class="new" href="https://developer.mozilla.org/fr/docs/Learn/HTML/Introduction_to_HTML" rel="nofollow"> </a>connaissances de base de <a class="new" href="https://developer.mozilla.org/fr/docs/Web/HTTP/Basics_of_HTTP" rel="nofollow">HTTP </a>et <a class="new" href="https://developer.mozilla.org/fr/docs/Learn/Server-side/First_steps" rel="nofollow">programmation côté serveur.</a></td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td>Comprendre ce qui arrive quand les données d'un formulaire sont soumises, y compris les notions de la façon dont les données sont traitées sur le serveur.</td> + </tr> + </tbody> +</table> + +<h2 id="Où_vont_les_données">Où vont les données ?</h2> + +<p>Dans ce paragraphe, nous expliquons ce qui arrive aux données lors de la soumission d'un formulaire.</p> + +<h3 id="A_propos_de_l'architecture_client_serveur">A propos de l'architecture client / serveur</h3> + +<p>Le web se fonde sur une architecture client/serveur élémentaire ; en résumé : un client (généralement un navigateur Web) envoie une requête à un serveur (le plus souvent un serveur web comme <a href="http://httpd.apache.org/" rel="external" title="http://www.apache.org/">Apache</a>, <a href="http://nginx.com/" rel="external" title="http://nginx.com/">Nginx</a>, <a href="http://www.iis.net/" rel="external" title="http://www.iis.net/">IIS</a>, <a href="http://tomcat.apache.org/" rel="external" title="http://tomcat.apache.org/">Tomcat</a>...), en utilisant le <a href="/fr/docs/HTTP">protocole HTTP</a>. Le serveur répond à la requête en utilisant le même protocole.</p> + +<p><img alt="Un schéma élémentaire d'architecture client/serveur sur le Web " src="https://mdn.mozillademos.org/files/16000/client-serveur.png" style="height: 141px; width: 400px;"></p> + +<p>Côté client, un formulaire HTML n'est rien d'autre qu'un moyen commode et convivial de configurer une requête HTTP pour envoyer des données à un serveur. L'utilisateur peut ainsi adresser des informations à joindre à la requête HTTP.</p> + +<div class="note"> +<p><strong>Note</strong>: Pour une meilleure idée du fonctionnement de l'architecture client‑serveur, lisez notre module <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps">Programmation d'un site web côté‑serveur : premiers pas</a>.</p> +</div> + +<h3 id="Côté_client_définition_de_la_méthode_d'envoi_des_données">Côté client : définition de la méthode d'envoi des données</h3> + +<p>L'élément {{HTMLElement("form")}} définit la méthode d'envoi des données. Tous ses attributs sont conçus pour vous permettre de configurer la requête à envoyer quand un utilisateur presse le bouton d'envoi. Les deux attributs les plus importants sont {{htmlattrxref("action","form")}} et {{htmlattrxref("method","form")}}.</p> + +<h4 id="L'attribut_htmlattrxref(actionform)">L'attribut {{htmlattrxref("action","form")}}</h4> + +<p>Cet attribut définit où les données sont envoyées. Sa valeur doit être une URL valide. S'il n'est pas fourni, les données seront envoyées à l'URL de la page contenant le formulaire.</p> + +<p>Dans cet exemple, les données sont envoyées à une URL précise — http://foo.com :</p> + +<pre class="brush: html"><form action="http://foo.com"></pre> + +<p class="brush: html">Ici, nous utilisons une URL relative — les données sont envoyées à une URL différente sur le serveur :</p> + +<pre class="brush: html"><form action="/somewhere_else"></pre> + +<p class="brush: html">Sans attribut, comme ci-dessous, les données de {{HTMLElement("form")}} sont envoyées à la même page que celle du formulaire :</p> + +<pre class="brush: html"><form></pre> + +<p class="brush: html">De nombreuses pages anciennes utilisent la notation suivante pour indiquer que les données doivent être envoyées à la page qui contient le formulaire. C'était nécessaire car jusqu'à HTML5, l'attribut {{htmlattrxref("action", "form")}} était requis. Il n'y en a donc plus besoin.</p> + +<pre class="brush: html"><form action="#"></pre> + +<div class="note"> +<p><strong>Note :</strong> Il est possible de spécifier une URL qui utilise le protocole HTTPS (HTTP sécurisé). Quand vous faites ceci, les données sont chiffrées avec le reste de la requête, même si le formulaire lui-même est hébergé dans une page non sécurisée à laquelle on accède via HTTP. D'autre part, si le formulaire est hébergé sur une page sécurisée mais qu'on spécifique une URL non sécurisée avec l'attribut {{htmlattrxref("action","form")}}, tous les navigateurs affichent une alerte de sécurité pour l'utilisateur chaque fois qu'il envoie des données car celles-ci ne sont pas chiffrées.</p> +</div> + +<h4 id="L'attribut_htmlattrxref(methodform)">L'attribut {{htmlattrxref("method","form")}}</h4> + +<p>Cet attribut définit comment les données sont envoyées. Le <a href="/fr/docs/HTTP">Protocole HTTP </a>fournit plusieurs façons d'envoyer une requête. Les données des formulaires HTML peuvent être envoyées via au moins deux méthodes : la méthode <code>GET</code> et la méthode <code>POST</code>.</p> + +<p>Pour bien comprendre la différence entre ces deux méthodes, il convient d'examiner comment le protocole HTTP marche. Chaque fois qu'on veut atteindre une ressource sur Internet, le navigateur envoie une requête à une URL. Une requête HTTP consiste en deux parties : un en-tête (header) qui contient les métadonnées sur les capacités du navigateur, et un corps (body) qui contient les informations nécessaires au serveur pour effectuer la requête.</p> + +<h5 id="La_méthode_GET">La méthode GET</h5> + +<p>La méthode <code>GET</code> est utilisée par le navigateur pour demander au serveur de renvoyer une certaine ressource. "Hé le serveur, je veux cette ressource." Dans ce cas, le navigateur envoie un corps vide. Du coup, si un formulaire est envoyé avec cette méthode, les données envoyées au serveur sont ajoutées à l'URL.</p> + +<p>Considérons le formulaire suivant :</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><form action="http://foo.com" method="get"> + <div> + <label for="say">Quel salut voulez-vous adresser ?</label> + <input name="say" id="say" value="Hi"> + </div> + <div> + <label for="to">À qui voulez‑vous l'adresser ?</label> + <input name="to" value="Mom"> + </div> + <div> + <button>Send my greetings</button> + </div> +</form></code></pre> + +<p>Comme nous avons utilisé la méthode <code>GET</code>, vous verrez l'URL <code>www.foo.com/?say=Hi&to=Mom</code> apparaître dans la barre du navigateur quand vous soumettez le formulaire.</p> + +<p><img alt="Message d'erreur: le serveur est introuvable" src="https://mdn.mozillademos.org/files/16002/fr-introuvable.png" style="display: block; height: 575px; margin: 0px auto; width: 748px;"></p> + +<p>Les données sont ajoutées à l'URL sous forme d'une suite de paires nom/valeur. À la fin de l'URL de l'adresse Web, il y a un point d'interrogation (?) suivi par les paires nom/valeur séparés par une esperluette (&). Dans ce cas, nous passons deux éléments de données au serveur :</p> + +<ul> + <li><code>say</code>, dont la valeur est <code>Hi</code></li> + <li><code>to</code>, qui a la valeur <code>Mom</code></li> +</ul> + +<p>La requête HTTP ressemble à quelque chose comme :</p> + +<pre class="line-numbers language-html"><code class="language-html">GET /?say=Hi&to=Mom HTTP/1.1 +Host: foo.com</code></pre> + +<div class="note"> +<p><strong>Note </strong>: Vous trouverez cet exemple sur GitHub — voyez <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/get-method.html">get-method.html</a> (à voir <a href="https://mdn.github.io/learning-area/html/forms/sending-form-data/get-method.html">directement aussi</a>).</p> +</div> + +<h5 id="La_méthode_POST">La méthode POST</h5> + +<p>La méthode <code>POST</code> est un peu différente.C'est la méthode que le navigateur utilise pour demander au serveur une réponse prenant en compte les données contenues dans le corps de la requête HTTP : « Hé serveur ! vois ces données et renvoie-moi le résultat approprié ». Si un formulaire est envoyé avec cette méthode, les données sont ajoutées au corps de la requête HTTP.</p> + +<p>Voyons un exemple — c'est le même formulaire que celui que nous avons vu pour GET ci‑dessus, mais avec <code>post</code> comme valeur de l'attribut {{htmlattrxref("method","form")}}.</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>form</span> <span class="attr-name token">action</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>http://foo.com<span class="punctuation token">"</span></span> <span class="attr-name token">method</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>post<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>say<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Quel salut voulez‑vous adresser ?<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>say<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>say<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>Hi<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>to<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>À qui voulez‑vous l'adresser ?<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>to<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>Mom<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>button</span><span class="punctuation token">></span></span>Send my greetings<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>button</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>div</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>form</span><span class="punctuation token">></span></span></code></pre> + +<p>Quand le formulaire est soumis avec la méthode <code>POST</code>, aucune donnée n'est ajoutée à l'URL et la requête HTTP ressemble à ceci, les données incorporées au corps de requête :</p> + +<pre>POST / HTTP/1.1 +Host: foo.com +Content-Type: application/x-www-form-urlencoded +Content-Length: 13 + +say=Hi&to=Mom</pre> + +<p>L'en-tête <code>Content-Length </code>indique la taille du corps, et l'en-tête <code>Content-Type</code> indique le type de ressources envoyées au serveur. Nous discuterons de ces en-têtes dans un moment.</p> + +<div class="note"> +<p><strong>Note </strong>: Vous trouverez cet exemple sur GitHub — voyez <a href="https://mdn.github.io/learning-area/html/forms/sending-form-data/post-method.html">post-method.html</a> (à voir <a href="https://mdn.github.io/learning-area/html/forms/sending-form-data/get-method.html">directement aussi</a>).</p> +</div> + +<h4 id="Voir_les_requêtes_HTTP">Voir les requêtes HTTP</h4> + +<p>Les requêtes HTTP ne sont jamais montrées à l'utilisateur (si vous voulez les voir, vous devez utiliser des outils comme la <a href="/en-US/docs/Tools/Web_Console" title="/en-US/docs/Tools/Web_Console">Console Web</a> de Firefox ou les <a href="https://developers.google.com/chrome-developer-tools/" title="https://developers.google.com/chrome-developer-tools/">Chrome Developer Tools</a>). À titre d'exemple, les données de formulaire sont visibles comme suit dans l'onglet Chrome Network. Après avoir soumis le formulaire :</p> + +<ol> + <li>Pressez F12</li> + <li>Selectionnez « Réseau »</li> + <li>Selectionnez « Tout »</li> + <li>Selectionnez « foo.com » dans l'onglet « Nom »</li> + <li>Selectionnez « En‑tête »</li> +</ol> + +<p>Vous obtiendrez les données du formulaire, comme l'image suivante le montre.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14691/network-monitor.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>La seule chose affichée à l'utilisateur est l'URL appelée. Comme mentionné ci‑dessus, avec une requête <code>GET</code> l'utilisateur verra les données dans la barre de l'URL, mais avec une requête <code>POST</code> il ne verra rien. Cela peut être important pour deux raisons :</p> + +<ol> + <li> + <p>Si vous avez besoin d'envoyer un mot de passe (ou toute autre donnée sensible), n'utilisez jamais la méthode GET ou vous risquez de l'afficher dans la barre d'URL, ce qui serait très peu sûr.</p> + </li> + <li> + <p>Si vous avez besoin d'envoyer une grande quantité de données, la méthode POST est préférable car certains navigateurs limitent la taille des URLs. De plus, de nombreux serveurs limitent la longueur des URL qu'ils acceptent.</p> + </li> +</ol> + +<h3 id="Côté_serveur_récupérer_les_données">Côté serveur : récupérer les données</h3> + +<p>Quelle que soit la méthode HTTP qu'on choisit, le serveur reçoit une chaîne de caractères qui sera décomposée pour récupérer les données comme une liste de paires clé/valeur. La façon d'accéder à cette liste dépend de la plateforme de développement utilisée et des modèles qu'on peut utiliser avec. La technologie utilisée détermine aussi comment les clés dupliquées sont gérées ; souvent, la priorité est donnée à la valeur de clé la plus récente.</p> + +<h4 id="Exemple_PHP_brut">Exemple : PHP brut</h4> + +<p>Le PHP met à disposition des objets globaux pour accéder aux données. En supposant que vous avez utilisé la méthode <code>POST</code>, l'exemple suivant récupère les données et les affiche à l'utilisateur. Bien sûr, ce que vous en faites dépend de vous. Vous pouvez les afficher, les ranger dans une base de données, les envoyer par mail ou les traiter autrement.</p> + +<pre class="brush: php"><?php + // La variable globale $_POST vous donne accès aux données envoyées avec la méthode POST par leur nom + // Pour avoir accès aux données envoyées avec la méthode GET, utilisez $_GET + $say = htmlspecialchars($_POST['say']); + $to = htmlspecialchars($_POST['to']); + + echo $say, ' ', $to;</pre> + +<p>Cet exemple affiche une page avec les données envoyées. Vous pouvez voir ceci opérer avec notre fichier exemple <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/php-example.html">php-example.html</a> — il contient le même formulaire exemple que celui vu précédemment avec la méthode <code>post</code> avec <code>php-example.php</code> en action. À la soumission du formulaire, il envoie les données de ce dernier à <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/php-example.php">php-example.php</a>, contenant le code ci‑dessus. Quand le code est exécuté, la sortie dans le navigateur est <code>Bonjour, M'an</code>.<img alt="L'exécution du code PHP déclenche l'affichage de Bonjour, M'an" src="https://mdn.mozillademos.org/files/16008/bonjour_man.png" style="display: block; height: 191px; margin: 0px auto; width: 474px;"></p> + +<div class="note"> +<p><strong>Note </strong>: Cet exemple ne fonctionnera pas si vous le chargez localement dans un navigateur — les navigateurs ne savent pas interpréter le code PHP, donc quand le formulaire est soumis, le navigateur vous offrira seulement de télécharger le fichier PHP pour vous. Pour qu'il s'exécute, il est nécessaire de lancer l'exemple par l'intermédiaire d'un serveur PHP de n'importe quel type. Les bons choix pour des tests locaux de PHP sont <a href="https://www.mamp.info/en/downloads/">MAMP</a> (Mac et Windows) et <a href="http://ampps.com/download">AMPPS</a> (Mac, Windows, Linux).</p> +</div> + +<h4 id="Exemple_Python">Exemple: Python</h4> + +<p>Cet exemple vous montre comment utiliser Python pour faire la même chose — afficher les données sur une page web. Celui‑ci utilise <a href="http://flask.pocoo.org/">Flask framework</a> pour le rendu des modèles, la gestion de la soumission des données du formulaire, etc (voyez <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/python-example.py">python-example.py</a>).</p> + +<pre class="line-numbers language-html"><code class="language-html">from flask import Flask, render_template, request +app = Flask(__name__) + +@app.route('/', methods=['GET', 'POST']) +def form(): + return render_template('form.html') + +@app.route('/hello', methods=['GET', 'POST']) +def hello(): + return render_template('greeting.html', say=request.form['say'], to=request.form['to']) + +if __name__ == "__main__": + app.run()</code></pre> + +<p>Les deux prototypes référencés dans le code ci‑dessus sont les suivants :</p> + +<ul> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/templates/form.html">form.html </a>: Le même formulaire que celui vu plus haut dans la section {{anch("La méthode POST")}} mais avec l'attribut <code>action</code> défini à la valeur <code>\{{url_for('hello')}}</code>. (C'est un modèle <a href="http://jinja.pocoo.org/docs/2.9/">Jinja2</a>, qui est HTML à la base mais peut contenir des appels à du code Python qui fait tourner le serveur web mis entre accolades. <code>url_for('hello')</code> dit en gros « à rediriger sur <code>/hello</code> quand le formulaire est soumis ».)</li> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/templates/greeting.html">greeting.html</a> : Ce modèle contient juste une ligne qui renvoie les deux éléments de donnée qui lui sont passées lors du rendu. Cela est effectué par l'intermédiaire de la fonction <code>hello()</code> vue plus haut qui s'exécute quand l'URL <code>/hello</code> est chargée dans le navigateur.</li> +</ul> + +<div class="note"> +<p><strong>Note </strong>: À nouveau, ce code ne fonctionnera pas si vous tentez de le charger directement dans le navigateur. Python fonctionne un peu différemment de PHP — pour exécuter ce code localement il est nécessaire d'<a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/development_environment#Installing_Python_3">installer Python/PIP</a>, puis Flask avec « <code>pip3 install flask</code> ». À ce moment‑là vous pourrez exécuter l'exemple avec « <code>python3 python-example.py</code> », puis en allant sur « <code>localhost:5000</code> » dans votre navigateur.</p> +</div> + +<h4 id="Autres_langages_et_canevas_de_structures">Autres langages et canevas de structures</h4> + +<p>Il y a de nombreuses autres techniques côté serveur utilisables pour gérer des formulaires, comme <a href="/fr/docs/" title="/en-US/docs/">Perl</a>, <a href="/fr/docs/" title="/en-US/docs/">Java</a>, <a href="http://www.microsoft.com/net" title="http://www.microsoft.com/net">.Net</a>, <a href="/fr/docs/" title="/en-US/docs/">Ruby</a>... retenez juste votre préférée. Cela dit, il faut noter qu'il n'est pas très courant d'utiliser ces techniques directement car cela peut être délicat. Il est plus fréquent d'utiliser l'un des jolis canevas qui permettent de gérer des formulaires plus facilement, comme :</p> + +<ul> + <li><a href="http://symfony.com/" rel="external" title="http://symfony.com/">Symfony</a> pour PHP</li> + <li><a href="https://www.djangoproject.com/" rel="external" title="https://www.djangoproject.com/">Django</a> pour Python</li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs">Express</a> pour Node.js</li> + <li><a href="http://rubyonrails.org/" rel="external" title="http://rubyonrails.org/">Ruby On Rails</a> pour Ruby</li> + <li><a href="http://grails.org/" rel="external" title="http://grails.org/">Grails</a> pour Java</li> + <li>etc.</li> +</ul> + +<p>Enfin il faut noter que même en utilisant ces canevas, travailler avec des formulaires n'est pas toujours <em>facile</em>. Mais c'est quand même bien plus facile que d'essayer d'en écrire vous‑même les fonctionnalités et cela vous économisera pas mal de temps.</p> + +<div class="note"> +<p><strong>Note </strong>: Nous déborderions du cadre de cet article en vous initiant aux langages côté serveur ou aux canevas. Les liens ci‑dessus vous donneront des informations si vous souhaitez en apprendre plus.</p> +</div> + +<h2 id="Cas_particulier_envoyer_des_fichiers">Cas particulier : envoyer des fichiers</h2> + +<p>L'envoi de fichiers avec une formulaire HTML est cas particulier. Les fichiers sont des données binaires — ou considérées comme telles — alors que toutes les autres données sont des données textuelles. Comme HTTP est un protocole de texte, il y a certaines conditions particulières à remplir pour gérer des données binaires.</p> + +<h3 id="L'attribut_htmlattrxref(enctypeform)">L'attribut {{htmlattrxref("enctype","form")}}</h3> + +<p>Cet attribut vous permet de préciser la valeur de l'en-tête HTTP <code>Content-Type</code> incorporé dans la requête générée au moment de la soumission du formulaire. Cet en-tête est très important car il indique au serveur le type de données envoyées. Par défaut, sa valeur est <code>application/x-www-form-urlencoded</code>. Ce qui signifie : « Ce sont des données de formulaire encodées à l'aide de paramètres URL ».</p> + +<p>Mais si vous voulez envoyer des fichiers, il faut faire deux choses en plus :</p> + +<ul> + <li>régler l'attribut {{htmlattrxref("method","form")}} à <code>POST</code> car un contenu de fichier ne peut pas être mis dans des paramètres d'URL.</li> + <li>régler la valeur de {{htmlattrxref("enctype","form")}} <code>à multipart/form-data</code> car les données seront coupées en plusieurs parties, une pour chaque fichier plus une pour les données dans le corps du formulaire (si du texte a aussi été entré dans le formulaire).</li> + <li>incorporer un ou plusieurs widgets de <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/The_native_form_widgets#File_picker">sélection de fichiers</a> pour permettre aux utilisateurs de choisir les fichiers à téléverser.</li> +</ul> + +<p> Par exemple :</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>form</span> <span class="attr-name token">method</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>post<span class="punctuation token">"</span></span> <span class="attr-name token">enctype</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>multipart/form-data<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>file<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Choose a file<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>file<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>file<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>myFile<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>button</span><span class="punctuation token">></span></span>Send the file<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>button</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>div</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>form</span><span class="punctuation token">></span></span></code></pre> + +<div class="note"> +<p><strong>Note :</strong> Certains navigateurs prennent en charge l'attribut {{htmlattrxref("multiple","input")}} de l'élément {{HTMLElement("input")}}pour envoyer plus d'un fichier avec seulement un élément d'entrée. La façon dont le serveur gère ces fichiers dépend de la technologie du serveur. Comme évoqué précédemment, utiliser un modèle rendra les choses plus faciles.</p> +</div> + +<div class="warning"> +<p><strong>Attention :</strong> De nombreux serveurs sont configurés avec une limite de taille pour les fichiers et les requêtes HTTP pour éviter les abus. Il est important de vérifier cette limite avec l'administrateur du serveur avant d'envoyer un fichier.</p> +</div> + +<h2 id="Problèmes_courants_de_sécurité">Problèmes courants de sécurité</h2> + +<p>Chaque fois qu'on envoie des données à un serveur, il faut considérer la sécurité. Les formulaires HTML sont l'un des principaux vecteurs d'attaque (emplacements d'où les attaques peuvent provenir) contre les serveurs. Les problèmes ne viennent jamais des formulaires eux-mêmes — ils proviennent de la façon dont les serveurs gèrent les données.</p> + +<p>Selon ce que vous faites, il y a quelques problèmes de sécurité bien connus que vous pouvez aisément contrer :</p> + +<h3 id="XSS_et_CSRF">XSS et CSRF</h3> + +<p>Les attaques Cross-Site Scripting (XSS) et Cross-Site Request Forgery (CSRF) sont des attaques fréquentes qui surviennent quand vous affichez des données renvoyées par un utilisateur à celui-ci ou à un autre utilisateur. </p> + +<p>XSS permet aux attaquants d'injecter des scripts côté‑client dans les pages Web vues par d'autres utilisateurs. La vulnérabilité au XSS peut être utilisée par les attaquants pour contourner les contrôles d'accès comme la<a href="/en-US/docs/JavaScript/Same_origin_policy_for_JavaScript" title="/en-US/docs/JavaScript/Same_origin_policy_for_JavaScript"> </a><span class="st"><a href="/fr/docs/JavaScript/Same_origin_policy_for_JavaScript">same-origin policy</a> (ou politique de même origine)</span>. Les effets de ces attaques peuvent aller d'une nuisance mineure à un risque significatif de sécurité.</p> + +<p>Les attaques CSRF sont similaires aux attaques XSS en ce qu'elles commencent de la même façon — en injectant des scripts côté‑client sur des pages Web — mais leur cible est différente. Les attaquants CSRF essaient d'accroître leurs privilèges pour atteindre ceux d'un utilisateur privilégié (par exemple l'administrateur du site) pour effectuer une action qu'ils ne devraient pas pouvoir faire (par exemple, envoyer des données à un utilisateur non habilité).</p> + +<p>Les attaques XSS exploitent la confiance qu'un utilisateur a pour un site, alors que les attaques CSRF exploitent la confiance qu'un site a pour ses utilisateurs.</p> + +<p>Pour éviter ces attaques, vous devez toujours vérifier les données qu'un utilisateur envoie à votre serveur et (si vous avez besoin de les afficher) essayez de ne pas afficher le contenu HTML tel que fourni par l'utilisateur. A la place, vous devez traiter les données fournies par l'utilisateur afin de ne pas les afficher verbatim. La quasi totalité des modèles du marché implémentent un filtre minimum qui enlève les éléments <span style="line-height: 1.5;">{{HTMLElement("script")}}, {{HTMLElement("iframe")}} et {{HTMLElement("object")}} des données envoyées par les utilisateurs. Cela permet d'atténuer les risques sans toutefois les éradiquer.</span></p> + +<h3 id="Injection_SQL">Injection SQL</h3> + +<p>L'injection SQL est un type d'attaque qui essaie d'effectuer certaines actions sur les bases de données utilisées par le site web cible. Cela consiste d'ordinaire à envoyer une requête SQL en espérant que le serveur l'exécutera (généralement quand le serveur essaie de ranger les informations envoyées par un utilisateur). C'est assurément l'un des <a href="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project" rel="external" title="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project">vecteurs d'attaque les plus fréquents contre les sites web</a>.</p> + +<p>Les conséquences peuvent être terribles, de la perte de données à l'accès à l'infrastructure en utilisant l'augmentation des privilèges. C'est une menace sérieuse et vous ne devez jamais ranger des données envoyées par un utilisateur sans asepsie préalable (par exemple en utilisant <code><a href="http://www.php.net/manual/en/function.mysql-real-escape-string.php" rel="external" title="http://www.php.net/manual/en/function.mysql-real-escape-string.php">mysql_real_escape_string()</a></code> sur une infrastructure PHP/MySQL).</p> + +<h3 id="Injection_d'en-tête_HTTP_et_injection_d'email">Injection d'en-tête HTTP et injection d'email</h3> + +<p>Ces attaques peuvent arrivent quand votre application construit des en-têtes HTTP ou des emails basés sur les données entrées par un utilisateur sur un formulaire. Elles ne vont pas directement endommager votre serveur ou affecter vos utilisateurs mais elles sont la porte ouverte à des problèmes plus graves comme le piratage de session ou les attaques par hameçonnage (phishing).</p> + +<p>Ces attaques sont généralement silencieuses et peuvent transformer votre serveur en <a href="http://en.wikipedia.org/wiki/Zombie_(computer_science)" rel="exernal" title="http://en.wikipedia.org/wiki/Zombie_(computer_science)">zombie</a>.</p> + +<h3 id="Soyez_paranoïaque_ne_faites_jamais_confiances_à_vos_utilisateurs">Soyez paranoïaque : ne faites jamais confiances à vos utilisateurs</h3> + +<p>Alors, comment combattre ces menaces ? Ce sujet va bien au-delà de ce guide mais il y a quelques règles à garder en tête. La principale est de ne jamais faire confiance à ses utilisateurs, vous-même compris : même un utilisateur de confiance peut s'être fait pirater.</p> + +<p>Toute donnée qui va dans un serveur doit être vérifiée et nettoyée. Toujours. Sans exception.</p> + +<ul> + <li>Échappez les caractères putativement dangereux. <span id="result_box" lang="fr"><span>Les caractères spécifiques avec lesquels vous devez être prudent varient selon le contexte dans lequel les données sont utilisées et de la plate-forme serveur que vous utilisez, mais tous les languages côté serveur ont des fonctions pour cela.</span></span></li> + <li><span id="result_box" lang="fr"><span>Limitez le volume des données entrantes pour n'autoriser que ce qui est nécessaire.</span></span></li> + <li><span id="result_box" lang="fr"><span>Faites passer par le bac à sable les fichiers téléversés (stockez‑les sur un serveur différent et n'autorisez l'accès au fichier que dans un sous-domaine différent, ou mieux, par un nom de domaine complètement différent).</span></span></li> +</ul> + +<p>Vous devriez vous éviter beaucoup de problèmes en suivant ces trois règles, mais cela reste néanmoins une bonne idée de faire un examen de sécurité auprès d'une tierce personne compétente. Ne pensez pas, à tort, avoir anticipé tous les problèmes de sécurité !</p> + +<div class="note"> +<p><strong>Note </strong>: L'article « <a href="/fr/docs/Learn/Server-side/First_steps/Website_security">Sécurité des sites Web</a> » de notre sujet d'apprentissage « <a href="/fr/docs/Learn/Server-side">côté‑serveur</a> » discute les problèmes ci‑dessus et leurs solutions possibles plus en détail.</p> +</div> + +<h2 id="Conclusion">Conclusion</h2> + +<p>Comme vous pouvez le voir, envoyer un formulaire est facile, mais sécuriser son application peut s'avérer plus délicat. <span id="result_box" lang="fr"><span>N'oubliez pas qu'un développeur n'est pas celui qui doit définir le modèle de sécurité des données.</span> <span>Comme nous allons le voir, il est possible d'effectuer la <a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">validation des données côté client</a>, mais le serveur ne peut pas faire confiance à cette validation car il n'a aucun moyen de savoir ce qui se passe réellement du côté client.</span></span></p> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<p>Si vous voulez en savoir plus par rapport aux applications web, vous pouvez consulter ces ressources :</p> + +<ul> + <li><a href="/fr/docs/Learn/Server-side/First_steps">Programmation d'un site web côté‑serveur : premiers pas</a></li> + <li><a href="https://www.owasp.org/index.php/Main_Page" rel="external" title="https://www.owasp.org/index.php/Main_Page">Open Web Application Security Project (OWASP)</a> (Projet pour la sécurité des applications dans un Web ouvert)</li> + <li><a href="http://shiflett.org/" rel="external" title="http://shiflett.org/">Blog de Chris Shiflett à propos de la sérité avec PHP</a></li> +</ul> + +<div> +<div>{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs", "Web/Guide/HTML/Formulaires/Validation_donnees_formulaire", "Web/Guide/HTML/Formulaires")}}</div> +</div> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML">Mon premier formulaire HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML"><span>Comment structurer un formulaire HTML</span></a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">Les widgets natifs pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets personnalisés pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">Mise en forme des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">Mise en forme avancée des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Table de compatibilité des propriétés pour les widgets de formulaire</a></li> +</ul> diff --git a/files/fr/web/guide/html/formulaires/html_forms_in_legacy_browsers/index.html b/files/fr/web/guide/html/formulaires/html_forms_in_legacy_browsers/index.html new file mode 100644 index 0000000000..6c1d043659 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/html_forms_in_legacy_browsers/index.html @@ -0,0 +1,220 @@ +--- +title: Formulaires HTML dans les navigateurs historiques +slug: Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers +translation_of: Learn/Forms/HTML_forms_in_legacy_browsers +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript", "Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML", "Web/Guide/HTML/Formulaires")}}</div> + +<p class="summary">Tout développeur apprend très rapidement (parfois difficilement) que le Web est un endroit assez inconfortable. Le pire des fléaux est le « navigateur historique ». Oui, admettons‑le, si on dit « navigateur historique », nous pensons tous aux anciennes versions d'Internet Explorer ... mais elles sont loin d'être les seules. Les premières versions de Firefox, comme la <a href="http://www.mozilla.org/en-US/firefox/organizations/" title="http://www.mozilla.org/en-US/firefox/organizations/">version ESR,</a> sont aussi des « navigateurs historiques ». Et dans le monde du mobile ? Quand ni le navigateur ni l'OS ne peut être mis à jour? Oui, il y a beaucoup de vieux smartphones Android ou des iPhones dont le navigateur par défaut n'est pas à jour. Ceux-ci sont aussi des « navigateurs historiques ».</p> + +<p>Malheureusement, parcourir cette jungle est une facette du métier. Mais opportunément, il existe quelques astuces pour nous aider à résoudre 80 % des problèmes causés par ces vieilles versions de navigateur.</p> + +<h2 id="S'informer_sur_les_difficultés">S'informer sur les difficultés</h2> + +<p>En fait, lire la documentation sur ces navigateurs est la chose la plus importante pour essayer de comprendre les modèles communs. Par exemple, la prise en charge des CSS est un problème majeur du formulaire HTML dans la plupart des cas. Vous êtes au bon endroit pour commencer. Il suffit de vérifier la prise en charge des éléments (ou interface DOM) que vous voulez utiliser. MDN dispose de tables de compatibilité pour de nombreux éléments, propriétés ou API pouvant être utilisées dans une page Web. Mais il existe d'autres ressources étonnamment utiles :</p> + +<h3 id="Documentation_du_fournisseur_du_navigateur">Documentation du fournisseur du navigateur</h3> + +<ul> + <li>Mozilla : vous êtes au bon endroit, explorez juste MDN</li> + <li>Microsoft : <a href="http://msdn.microsoft.com/en-us/library/ff410218%28v=vs.85%29.aspx" rel="external" title="http://msdn.microsoft.com/en-us/library/ff410218%28v=vs.85%29.aspx">Documentation sur la prise en charge de la norme par Internet Explorer</a></li> + <li>WebKit : comme il y a plusieurs versions de ce moteur, les choses se compliquent : + <ul> + <li><a href="https://www.webkit.org/blog/" rel="external" title="https://www.webkit.org/blog/">le Blog WebKit</a> et <a href="http://planet.webkit.org/" rel="external" title="http://planet.webkit.org/">Planet WebKit</a> rassemblent les meilleurs articles par les déveoppeurs WebKit.</li> + <li><a href="https://www.chromestatus.com/features" title="http://www.chromium.org/developers/web-platform-status">l</a>e site État de la p<a href="https://www.chromestatus.com/features" title="http://www.chromium.org/developers/web-platform-status">lateforme Chrome</a> est aussi importante.</li> + <li>ainsi que le<a href="https://developer.apple.com/technologies/safari/" rel="external" title="https://developer.apple.com/technologies/safari/"> site web Apple .</a></li> + </ul> + </li> +</ul> + +<h3 id="Documentation_indépendante">Documentation indépendante</h3> + +<ul> + <li><a href="http://caniuse.com" rel="external" title="http://caniuse.com">Can I Use</a> a des informations sur la prise en charge des techniques avancées. </li> + <li><a href="http://www.quirksmode.org" rel="external" title="http://www.quirksmode.org">Quirks Mode</a> est une surprenante ressource sur la compatibilité des divers navigateurs. <a href="http://www.quirksmode.org/mobile/" rel="external" title="http://www.quirksmode.org/mobile/">La partie sur les mobiles</a> est la meilleure actuellement disponible.</li> + <li><a href="http://positioniseverything.net/" rel="external" title="http://positioniseverything.net/">Position Is Everything</a> est la meilleure ressource disponible sur les bogues de rendu dans les navigateurs historiques et leur solution de contournement (le cas échéant).</li> + <li><a href="http://mobilehtml5.org" rel="external" title="http://mobilehtml5.org">Mobile HTML5</a> dispose d'informations de compatibilité pour une large gamme de navigateurs pour mobiles, et pas seulement pour le « top 5 » (y compris Nokia, Amazon et Blackberry).</li> +</ul> + +<h2 id="Rendre_les_choses_simples">Rendre les choses simples</h2> + +<p> </p> + +<p>Comme les <a href="/fr/docs/Web/Guide/HTML/Formulaires">formulaires HTML</a> impliquent des interactions complexes, une règle empirique : <a href="https://fr.wikipedia.org/wiki/Principe_KISS">restez aussi simple que possible</a>. Il y a tant de cas où nous voudrions que des formulaires soient « plus beaux » ou « avec des fonctionnalités avancées » ! Mais construire des formulaires HTML efficaces n'est pas une question de design ou de technique. Pour rappel, prenez le temps de lire cet article sur l'<a href="http://www.uxforthemasses.com/forms-usability/">ergonomie des formulaires sur UX For The Masses</a> (en anglais).</p> + +<h3 id="La_simplification_élégante_est_la_meilleure_amie_du_développeur_Web">La simplification élégante est la meilleure amie du développeur Web</h3> + +<p><a href="http://www.sitepoint.com/progressive-enhancement-graceful-degradation-choice/" rel="external" title="http://www.sitepoint.com/progressive-enhancement-graceful-degradation-choice/">Une simplification élégante et des améliorations progressives</a> sont des modèles de développement qui permettent de construire des grands projets prenant en charge une large gamme de navigateurs simultanément. Quand vous créez quelque chose pour un navigateur moderne, et que vous voudriez être sûrs que, l'un l'autre, il fonctionne sur des navigateurs historiques, vous faites de la simplification élégante.</p> + +<p>Voyons quelques exemples relatifs aux formulaires en HTML.</p> + +<h4 id="Types_d'entrées_en_HTML">Types d'entrées en HTML</h4> + +<p>Les nouveaux types d'entrées amenés par HTML5 sont très sympas car la façon dont ils simplifient est grandement prévisible. Si un navigateur ne connaît pas la valeur de l'attribut {{htmlattrxref("type","input")}} d'un élément {{HTMLElement("input")}}, il prendra une valeur <code>text</code> en recours.</p> + +<pre class="brush: html"><label for="myColor"> + Choisir une couleur + <input type="color" id="myColor" name="color"> +</label></pre> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Chrome 24</th> + <th scope="col" style="text-align: center;">Firefox 18</th> + </tr> + </thead> + <tbody> + <tr> + <th style="text-align: center;"><img alt="Capture d'écran de l'entrée de couleur sur Chrome pour Mac OSX" src="https://mdn.mozillademos.org/files/16009/choix_chrome.png" style="height: 32px; width: 227px;"></th> + <th style="text-align: center;"><img alt="Capture d'écran de l'entrée de couleur sur Firefox" src="https://mdn.mozillademos.org/files/16010/choix_firefox.png" style="height: 36px; width: 227px;"></th> + </tr> + </tbody> +</table> + +<h4 id="Sélecteurs_d'attributs_CSS">Sélecteurs d'attributs CSS</h4> + +<p>Les <a href="/fr/docs/Web/CSS/Sélecteurs_d_attribut" title="/en-US/docs/CSS/Attribute_selectors">sélecteurs d'attributs CSS</a> sont très utiles avec les <a href="/fr/docs/Web/Guide/HTML/Formulaires">formulaires HTML</a>, mais certains navigateurs historiques ne les prennent pas en charge. Dans ce cas, il est courant de doubler le type avec une classe équivalente :</p> + +<pre class="brush: html"><input type="number" class="number"></pre> + +<pre class="brush: css">input[type=number] { + /* Ceci peut échouer avec certains navigateurs */ +} + +input.number { + /* Ceci fonctionne partout */ +}</pre> + +<p>Notez que ce qui suit n'est pas utile (car redondant) et peut échouer dans certains navigateurs :</p> + +<pre class="brush: css">input[type=number], +input.number { + /* Ceci peut échouer dans certains navigateurs ; s'il ne comprennent pas + l'un des sélecteurs, il sautent la totalité de la règle */ +}</pre> + +<h4 id="Boutons_et_formulaires">Boutons et formulaires</h4> + +<p>Il y a deux manières de définir un bouton dans un formulaire HTML :</p> + +<ul> + <li>un élément {{HTMLElement("input")}} avec un attribut {htmlattrxref("type","input")}} défini avec une des valeurs <code>button</code>, <code>submit</code>, <code>reset</code> ou <code>image</code></li> + <li>un élément {{HTMLElement("button")}}</li> +</ul> + +<p>L'élément {{HTMLElement("input")}} peut rendre les choses compliquées si vous voulez appliquer des CSS avec un sélecteur d'élément :</p> + +<pre class="brush: html"><input type="button" class="button" value="Cliquez‑moi"></pre> + +<pre class="brush: css">input { + /* Cette règle annule le rendu par défaut défini avec un élément input */ + border: 1px solid #CCC; +} + +input.button { + /* Le rendu par défaut N'EST PAS restauré avec ceci */ + border: none; +} + +input.button { + /* Avec ceci non plus ! En fait, il n'y a pas de méthode standard pour + le faire quel que soit le navigateur */ + border: auto; +}</pre> + +<p>L'élément {{HTMLElement("button")}} présente deux problèmes potentiels :</p> + +<ul> + <li> + <p>un bogue dans certaines anciennes versions d'Internet Explorer. Lorsque l'utilisateur clique sur le bouton, ce n'est pas le contenu de l'attribut {{htmlattrxref("value", "button")}} qui est envoyé, mais le contenu HTML disponible entre balises de début et de fin de l'élément {{HTMLElement("button")}}. Ce n'est un problème que si vous voulez envoyer une telle valeur, par exemple si le traitement des données dépend du bouton sur lequel l'utilisateur clique.</p> + </li> + <li>certains navigateurs très anciens n'utilisent pas <code>submit</code> comme valeur par défaut pour l'attribut {{htmlattrxref("type","button")}}, donc il est recommandé de toujours définir l'attribut {{htmlattrxref("type","button")}} pour les éléments {{HTMLElement("button")}}.</li> +</ul> + +<pre class="brush: html"><!-- Cliquer sur ce boutton envoie « <em>Do A</em> » au lieu de « A » dans certains cas --> +<button type="submit" name="IWantTo" value="A"> + <em>Do A</em> +</button></pre> + +<p>Le choix de l'une ou l'autre solution vous appartient, selon les contraintes du projet.</p> + +<h3 id="Laissez_tomber_les_CSS">Laissez tomber les CSS</h3> + +<p>Le plus gros problème avec les formulaires HTML et les navigateurs historiques est la prise en charge des CSS. Comme vous pouvez le constater, vu la complexité de la <a href="/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Table de compatibilité des propriétés pour les widgets de formulaire</a>, c'est très difficile. Même s'il est toujours possible de faire quelques ajustements sur les éléments de texte (comme la taille ou la couleur de police), il y a toujours des effets secondaires. La meilleure approche reste de ne faire aucune composition des widgets de formulaire HTML. Mais vous pouvez toujours appliquer des styles à tous les éléments environnants. Si vous êtes un professionnel et que votre client le réclame, dans ce cas, vous pouvez étudier certaines techniques difficiles telles que la <a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">construction de widgets avec JavaScript</a>. Mais dans ce cas, n'hésitez pas à facturer votre client pour ce caprice.</p> + +<h2 id="Détection_de_fonctionnalité_et_prothèses_d'émulation_(polyfills)">Détection de fonctionnalité et prothèses d'émulation (<em>polyfills</em>)</h2> + +<p>Bien que JavaScript soit un langage de programmation remarquable pour les navigateurs modernes, les navigateurs historiques ont de nombreux problèmes avec cette technique.</p> + +<h3 id="JavaScript_non_obstructif">JavaScript non obstructif</h3> + +<p>Un des plus gros problèmes est la disponibilité des API. Pour cette raison, il est considéré comme de bonne pratique de travailler avec du JavaScript « non obstructif ». C'est un modèle de développement défini par deux obligations :</p> + +<ul> + <li>une séparation stricte entre structure et comportement.</li> + <li>si le fil du code casse, le contenu et les fonctionnalités de base doivent rester accessibles et utilisables.</li> +</ul> + +<p><a href="http://docs.webplatform.org/wiki/concepts/programming/the_principles_of_unobtrusive_javascript" rel="external" title="http://docs.webplatform.org/wiki/concepts/programming/the_principles_of_unobtrusive_javascript">Les principes d'un JavaScript non obstructif</a> (écrit à l'origine par Peter-Paul Koch pour Dev.Opera.com et maintenant mis sur Docs.WebPlatform.org) descrit très bien ces idées.</p> + +<h3 id="La_bibliothèque_Modernizr">La bibliothèque Modernizr</h3> + +<p>Dans de nombreux cas, une bonne prothèse d'émulation (« polyfill ») peut aider en fournissant une API manquante. Un « <a href="http://remysharp.com/2010/10/08/what-is-a-polyfill/" rel="external" title="http://remysharp.com/2010/10/08/what-is-a-polyfill/">polyfill »</a> est un petit morceau de JavaScript qui « remplit un trou » dans les fonctionnalités des navigateurs historiques. Bien qu'ils puissent être utilisés pour améliorer la prise en charge de n'importe quelle fonctionnalité, leur utilisation dans le JavaScript est moins risquée que dans les CSS ou le HTML ; il existe de nombreux cas où JavaScript peut casser (problèmes de réseau, conflits de script, etc.). Mais avec le JavaScript, à condition de travailler avec un JavaScript non obstructif, si les polyfills manquent, ce ne sera pas grave.</p> + +<p>La meilleure façon de remplir un trou d'API manquante consiste à utiliser la bibliothèque <a href="http://modernizr.com" rel="external" title="http://modernizr.com">Modernizr</a> et son projet dérivé : <a href="http://yepnopejs.com" rel="external" title="http://yepnopejs.com">YepNope</a>. Modernizr est une bibliothèque qui vous permet de tester la disponibilité d'une fonctionnalité pour une action en accord. YepNope est une bibliothèqe de chargements conditionnels.</p> + +<p>Voici un exemple :</p> + +<pre class="brush: js">Modernizr.load({ + // Cette ligne teste si le navigateur prend en charge l'API + // de validation de formulaires HTML5 + test : Modernizr.formvalidation, + + // Si ce n'est pas le cas, le polyfill suivant sera chargé + nope : form-validation-API-polyfill.js, + + // En tout cas, le fichier au cœur de l'application, et dont elle dépend, + // est chargé + both : app.js, + + // Une fois les deux fichiers chargés, cette fonction est appelée + // dans le but d'initialiser l'application + complete : function () { + app.init(); + } +});</pre> + +<p>L'équipe de Modernizr fait une maintenance opportune de grande liste de « <a href="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills" rel="external" title="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills">polyfills »</a>. Prenez celui dont vous avez besoin.</p> + +<div class="note"> +<p><strong>Note :</strong> Modernizr a d'autres fonctionnalités remarquables pour faciliter le traitement du JavaScript non obstructif et les tecniques de simplifications élégantes. Prenez connaissance de <a href="http://modernizr.com/docs/" rel="external" title="http://modernizr.com/docs/"> la documentation de Modernizr</a>.</p> +</div> + +<h3 id="Faites_attention_aux_performances">Faites attention aux performances</h3> + +<p>Même si des scripts comme Modernizr sont très attentifs aux performances, le chargement d'un polyfill de 200 kilooctets peut affecter les performances de votre application. Ceci est particulièrement critique avec les navigateurs historiques ; beaucoup d'entre eux ont un moteur JavaScript très lent qui peut rendre l'exécution de tous vos polyfills pénibles pour l'utilisateur. La performance est un sujet en soi ; les navigateurs historiques y sont très sensibles : fondamentalement, ils sont lents et ils ont plus besoin de polyfills, et donc ils ont besoin de traiter encore plus de JavaScript. Ils sont donc doublement surchargés par rapport aux navigateurs modernes. Testez votre code avec les navigateurs historiques pour voir comment leur fonctionnement en conditions réelles. Parfois, l'abandon de certaines fonctionnalités amène un meilleur ressenti pour l'utilisateur que d'avoir exactement la même fonctionnalité dans tous les navigateurs. Dernier rappel : pensez toujours à l'utilisateur final.</p> + +<h2 id="Conclusion">Conclusion</h2> + +<p>Comme vous pouvez le constater, opérer avec des navigateurs historiques n'est pas qu'une question de formulaires. C'est tout un ensemble de techniques ; mais les maîtriser toutes dépasserait le cadre de cet article.</p> + +<p>Si vous avez lu tous les articles de ce <a href="/fr/docs/Web/Guide/HTML/Forms_in_HTML">guide à propos des formulaires en HTML</a>, vous devriez maintenant être à l'aise avec leur utilisation. Si vous trouvez de nouvelles techniques ou de nouvelles astuces, aidez‑nous à <a href="/fr/docs/MDN/Débuter_sur_MDN">améliorer ce guide</a>.</p> + +<p>{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript", "Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML", "Web/Guide/HTML/Formulaires")}}</p> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML">Mon premier formulaire HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML"><span>Comment structurer un formulaire HTML</span></a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">Les widgets natifs pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets personnalisés pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">Mise en forme des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">Mise en forme avancée des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Table de compatibilité des propriétés pour les widgets de formulaire</a></li> +</ul> diff --git a/files/fr/web/guide/html/formulaires/index.html b/files/fr/web/guide/html/formulaires/index.html new file mode 100644 index 0000000000..9927bd3385 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/index.html @@ -0,0 +1,81 @@ +--- +title: Formulaires HTML +slug: Web/Guide/HTML/Formulaires +tags: + - Apprentissage + - Featured + - Formulaires + - Guide + - HTML + - Web +translation_of: Learn/Forms +--- +<p>{{learnSidebar}}</p> + +<blockquote> +<p><span class="seoSummary">Ce guide est constitué d'une série d'articles qui vous aideront à maîtriser les formulaires HTML</span>. Les formulaires HTML sont des outils très puissants pour interagir avec l'utilisateur ; toutefois, à cause de raisons historiques et techniques, il n'est pas forcément évident de savoir comment les utiliser de manière optimale. Nous allons aborder tous les aspects des formulaires HTML, de la structure à la décoration, de la gestion des données aux widgets sur-mesure.</p> +</blockquote> + +<h2 id="Prérequis">Prérequis</h2> + +<p>Avant de vous lancer dans ce module, vous devez au moins avoir travaillé notre <a href="/fr/docs/Apprendre/HTML/Introduction_à_HTML">Introduction au HTML</a>. À partir de là, vous devriez trouver les {{anch("Éléments de base")}} faciles à comprendre et également être capable de vous servir du guide pour les <a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">widgets natifs pour formulaire</a>.</p> + +<p>Le reste du module est toutefois un peu plus difficile — il est facile de placer des widgets de formulaire dans une page, mais vous ne pourrez pas en faire vraiment quelque chose sans utiliser quelques fonctionnalités plus avancées, les CSS et le JavaScript. C'est pourquoi, avant de regarder ces autres parties, nous vous recommandons de faire un détour et de procéder d'abord à l'étude des <a href="/fr/Apprendre/CSS/Introduction_à_CSS">CSS</a> et du <a href="/fr/docs/Apprendre/JavaScript">JavaScript</a>.</p> + +<div class="note"> +<p><strong>Note</strong> : Si vous travaillez sur un ordinateur/tablette/autre appareil sur lequel vous n'avez pas la possiblité de créer vos propres fichiers, vous pourrez essayer (la pluspart) des exemples de code sur un programme de codage en ligne comme <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Éléments_de_base"><a id="Basic_guides" name="Basic_guides"></a>Éléments de base</h2> + +<dl> + <dt><a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML">Mon premier formulaire HTML</a></dt> + <dd>Le premier article de notre série vous donne une toute première expérience de création de formulaire en HTML, y compris sa conception, sa mise en œuvre en utilisant les bons éléments HTML, l'ajout de quelques très simples décorations avec les CSS et le comment de l'envoi des données à un serveur.</dd> + <dt><a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML" title="/fr/docs/HTML/Formulaires/Comment_structurer_un_formulaire_HTML"><span>Comment structurer un formulaire HTML</span></a></dt> + <dd>Les bases vues, nous examinons maintenant plus en détail les éléments utilisés pour structurer et donner un sens aux différentes parties d'un formulaire.</dd> +</dl> + +<h2 id="Quels_sont_les_widgets_pour_formulaire_disponibles">Quels sont les widgets pour formulaire disponibles ?</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">Les widgets natifs pour formulaire</a></dt> + <dd>Nous examinons maintenant en détail les fonctionnalités des widgets pour formulaire, en regardant quelles sont les options disponibles pour collecter différentes types de données.</dd> +</dl> + +<h2 id="Validation_et_soumission_des_données_de_formulaires">Validation et soumission des données de formulaires</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_donn%C3%A9es_des_formulaires">Envoi des données de formulaire</a></dt> + <dd>Cet article examine ce qui arrive quand un utilisateur soumet un formulaire — où les données vont-elles et comment les gère-t-on une fois à destination ? Nous examinerons aussi quelques problèmes de sécurité associés à l'envoi des données d'un formulaire.</dd> + <dt><a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Validation des données de formulaire</a></dt> + <dd>Ce n'est pas tout d'envoyer des données — il faut aussi s'assurer que les données mises dans un formulaire par un utilisateur sont de format correct pour pouvoir les traiter correctement et qu'elles ne vont pas casser nos applications. Nous voulons également aider les utilisateurs à compléter les formulaires correctement et à ne pas ressentir de frustration en essayant d'utiliser nos applications. La validation et la soumission des données des formulaires vous aidera à remplir ces objectifs — cet article indique ce qui est nécessaire de savoir.</dd> +</dl> + +<h2 id="Guides_avancés">Guides avancés</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets de formulaires personnalisés</a></dt> + <dd>Nous allons voir quelques cas où les widgets natifs ne donnent pas ce dont vous avez besoin, pour des raisons fonctionnelles ou de style par exemple. Dans de tels cas, vous pouvez avoir besoin de construire vous même un widget de formulaire en dehors du HTML brut. Cet article explique comment faire, ainsi que les considérations à prendre en compte ce faisant, le tout à l'aide de l'étude d'un cas particulier.</dd> + <dt><a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></dt> + <dd>Cet article examine les manières d'utiliser un formulaire pour assembler une requête HTTP et l'adresser par l'intermédiaire d'un JavaScript personnalisé, au lieu d'une soumission standard de formulaire. Il examine aussi pourquoi vous pouvez souhaiter faire ainsi et ce que cela implique corrélativement. (Voir aussi « Utilisation des objets FormData ».)</dd> + <dt><a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></dt> + <dd>Cet article couvre les détections de fonctionnalité, etc. Elles doivent être redirigées dans le module de tests croisés entre navigateurs, car la même problématique y sera mieux traitée.</dd> +</dl> + +<h2 id="Guides_de_mise_en_forme_des_formulaires">Guides de mise en forme des formulaires</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">Mise en forme des formulaires HTML</a></dt> + <dd>Cet article est une introduction à la mise en forme des formulaires à l'aide des CSS, y compris tous les éléments de base qu'il est nécessaire de connaître pour les tâches de décoration élémentaires.</dd> + <dt><a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">Mise en forme avancée des formulaires HTML</a></dt> + <dd>Dans cet article, nous regarderons des techniques de mise en forme plus avancées qu'il est nécessaire d'utiliser pour opérer sur les éléments les plus difficiles à traiter.</dd> + <dt><a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Tableau de compatibilité des propriétés entre widgets de formulaire</a></dt> + <dd>Ce dernier article fournit un référentiel pratique vous permettant de rechercher quelles propriétés des CSS sont compatibles avec tel ou tel élément de formulaire.</dd> +</dl> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li><a href="/fr/docs/Web/HTML/Element#Forms">Référentiel pour éléments de formulaire HTML</a></li> + <li><a href="/fr/docs/Web/HTML/Element/input">Référentiel pour les types <input> en HTML</a></li> +</ul> diff --git a/files/fr/web/guide/html/formulaires/les_blocs_de_formulaires_natifs/index.html b/files/fr/web/guide/html/formulaires/les_blocs_de_formulaires_natifs/index.html new file mode 100644 index 0000000000..97c4a12af6 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/les_blocs_de_formulaires_natifs/index.html @@ -0,0 +1,683 @@ +--- +title: Les widgets de formulaire natifs +slug: Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs +tags: + - Contrôles + - Exemple + - Formulaires + - Guide + - HTML + - Web + - Widgets +translation_of: Learn/Forms/Basic_native_form_controls +--- +<div>{{LearnSidebar}}<br> +{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML", "Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires", "Web/Guide/HTML/Formulaires")}}</div> + +<p class="summary">Nous examinerons maintenant en détail les fonctionnalités des divers widgets pour formulaires, en soulignant les options disponibles pour collecter les différents types de données. Ce guide vise à être exhaustif en couvrant tous les widgets natifs de formulaire disponibles.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td>Notions concernant les ordinateurs et les <a class="new" href="https://developer.mozilla.org/fr/docs/Apprendre/HTML/Introduction_à_HTML" rel="nofollow">connaissances de base du HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td>Comprendre quels sont les types de widgets de forme native disponibles dans les navigateurs pour collecter des données et comment les mettre en œuvre en se servant du HTML.</td> + </tr> + </tbody> +</table> + +<p>Ici, nous nous attarderons sur les widgets de formulaires intégrés aux navigateurs, mais comme les formulaires HTML restent très circonscrits et que la qualité des implémentations peut être très différente d'un navigateur à l'autre, les développeurs web construisent parfois leurs propres widgets de formulaires — voir <a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets de formulaires personnalisés</a> plus loin dans ce même module pour plus d'idées à ce propos.</p> + +<div class="note"> +<p><strong>Note </strong>: La plupart des fonctionnalités discutées dans cet article sont abondamment explicitées dans les navigateurs ; nous soulignerons les exceptions à ce sujet. Si vous voulez plus de précisions, consultez les <a href="/fr/docs/Web/HTML/Element#Forms">références aux éléments de formulaires HTML</a>, et en particulier nos références détaillées aux <a href="/fr/docs/Web/HTML/Element/input">types <input></a>.</p> +</div> + +<h2 id="Attributs_communs">Attributs communs</h2> + +<p>Beaucoup d'éléments utilisés pour définir les widgets de formulaire ont leurs propres attributs. Cependant, il y a un jeu d'attributs communs à tous les éléments de formulaire. Il vous permettent un certain contrôle sur ces widgets. Voici une liste de ces attributs communs :</p> + +<table> + <thead> + <tr> + <th scope="col">Nom de l'attribut</th> + <th scope="col">Valeur par défaut</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>autofocus</code></td> + <td>(<em>false</em>)</td> + <td>Cet attribut, booléen, vous permet de spécifier que cet élément doit avoir automatiquement le focus au chargement de la page, sauf si l'utilisateur prend la main, en faisant, par exemple, une saisie dans un autre contrôle. Un seul élément associé à une forme peut avoir cet attribut activé.</td> + </tr> + <tr> + <td><code>disabled</code></td> + <td>(<em>false</em>)</td> + <td>Cet attribut est un booléen. Il indique que l'utilisateur ne peut pas avoir d'action sur cet élément. S'il n'est pas précisé, l'élément hérite son comportement de l'élément contenant, comme, {{HTMLElement("fieldset")}} ; si le conteneur n'a pas d'attribut <code>disabled</code> mis, l'élément est activé.</td> + </tr> + <tr> + <td><code>form</code></td> + <td></td> + <td>L'élément <form> auquel le widget est associé. La valeur de l'attribut doit être l'attribut <code>id</code> d'un élément {{HTMLElement("form")}} dans le même document. En théorie, il vous permet de mettre un widget en dehors d'un élément {{HTMLElement("form")}}. En pratique, toutefois, il n'y a pas de navigateur qui prenne en charge cette fonctionnalité.</td> + </tr> + <tr> + <td><code>name</code></td> + <td></td> + <td>Le nom de l'élément ; il sera soumis en même temps que les données du formulaire.</td> + </tr> + <tr> + <td><code>value</code></td> + <td></td> + <td>La valeur initiale de l'élément.</td> + </tr> + </tbody> +</table> + +<h2 id="Champs_de_saisie_de_texte">Champs de saisie de texte</h2> + +<p>Les champs {{htmlelement("input")}} de saisie de texte sont les widgets de formulaire les plus élémentaires. Ils sont très pratiques pour permettre à un utilisateur de saisir n'importe quel type de données. Toutefois, certains champs textuels peuvent être spécialisés pour répondre à des besoins précis. Nous avons déjà vu quelques exemples.</p> + +<div class="note"> +<p><strong>Note :</strong> Les champs textuels dans les formulaires HTML sont des contrôles de saisie de texte brut. Cela signifie que vous ne pouvez pas les utiliser pour réaliser de la <a href="/en-US/docs/Rich-Text_Editing_in_Mozilla" title="/en-US/docs/Rich-Text_Editing_in_Mozilla">mise en forme riche</a> (gras, italique, etc.). Tous les éditeurs de textes évolués que vous rencontrez utilisent des widgets personnalisés créés avec HTML, CSS et JavaScript.</p> +</div> + +<p>Tous les champs textuels ont des comportement en commun :</p> + +<ul> + <li>Il peuvent être définis comme {{htmlattrxref("readonly","input")}} (l'utilisateur ne peut pas modifier la valeur) voire {{htmlattrxref("disabled","input")}} (la valeur n'est pas envoyé avec le restant des données du formulaire).</li> + <li>Ils peuvent avoir un {{htmlattrxref("placeholder","input")}}. Ce texte apparaît dans le champs de saisie et décrit brièvement le rôle de cette boîte.</li> + <li>Des contraintes peuvent leur être imposées avec {{htmlattrxref("size","input")}} (la taille physique de la boîte) et avec {{htmlattrxref("maxlength","input")}} (le nombre maximum de caractères qui peuvent être saisis dans la boîte).</li> + <li>Ils peuvent bénéficier d'une <a href="/fr/docs/HTML/Element/input#attr-spellcheck" title="/fr/docs/HTML/Element/input#attr-spellcheck">correction orthographique</a>, si le navigateur la prend en charge.</li> +</ul> + +<div class="note"> +<p><strong>Note :</strong> L'élément {{htmlelement("input")}} est spécial car il peut être pratiquement n'importe quoi. En réglant simplement ses attributs de type, il peut changer radicalement, et il est utilisé pour créer la plupart des types de widgets de formulaire allant des champs texte sur une seule ligne, contrôles sans entrée de texte, contrôles de date et heure jusqu'aux boutons. Il y a toutefois des exceptions, comme {{htmlelement("textarea")}} pour les entrées multi-lignes. Prenez bien note de ceci en lisant cet article.</p> +</div> + +<h3 id="Champs_texte_sur_une_seule_ligne"> Champs texte sur une seule ligne</h3> + +<p>On crée un champ texte sur une seule ligne avec l'élément {{HTMLElement("input")}} dont l'attribut {{htmlattrxref("type", "input")}} est mis à <code>text</code> (maisi, si vous n'indiquez pas l'attribut {{htmlattrxref("type", "input")}}, <code>text</code> est la valeur par défaut). <code>text</code> est aussi la valeur de repli si celle indiquée pour l'attribut {{htmlattrxref("type", "input")}} est inconnue du navigateur (par exemple, si vous spécifiez <code>type="date"</code> et que le navigateur ne prend pas en charge les sélecteurs de date natifs).</p> + +<div class="note"> +<p><strong>Note :</strong> Vous trouverez des exemples de tous les types de champ texte sur une ligne dans GitHub à <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/single-line-text-fields.html">single-line-text-fields.html</a> (voir <a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/single-line-text-fields.html">directement aussi</a>).</p> +</div> + +<p>Voici un exemple élémentaire de champ texte sur une ligne :</p> + +<pre class="brush: html"><input type="text" id="comment" name="comment" value="Je suis un champ texte"></pre> + +<p>Les champs texte sur une ligne n'ont qu'une seule contrainte : si vous saisissez du texte avec des sauts de ligne, le navigateur les supprime avant d'envoyer les données.</p> + +<p><img alt="Screenshots of single line text fields on several platforms." src="https://developer.mozilla.org/files/4273/all-single-line-text-field.png" style="height: 235px; width: 655px;"></p> + +<p>HTML5 améliore le champ texte élémentaire sur une ligne par ajout de valeurs spéciales pour l'attribut {{htmlattrxref("type","input")}}. Ces valeurs conservent l'élément {{HTMLElement("input")}} en tant que champ texte sur une ligne mais ajoutent quelques contraintes et caractéristiques supplémentaires au champ.</p> + +<h4 id="Champ_dadresse_électronique">Champ d'adresse électronique</h4> + +<p>Ce type de champ est défini en donnant la valeur <code>email</code> à l'attribut {{htmlattrxref("type","input")}} :</p> + +<pre class="brush: html"> <input type="email" <code class="language-html"><span class="tag token"><span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>email<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>email<span class="punctuation token">"</span></span> </span></code>multiple></pre> + +<p>Avec ce <code>type</code> , l'utilisateur doit saisir un e‑mail valide dans le champ. Tout autre type de contenu amène le navigateur à émettre une erreur lors de la soumission du formulaire. Notez que cette validation s'opère côté client et est faite par le navigateur :</p> + +<p><img alt="Entrée d'un e-mail non valide déclenchant un message d'avertissement « Veuillez saisir une adresse électronique valide »" src="https://mdn.mozillademos.org/files/16001/fr-email.png" style="border-style: solid; border-width: 1px; display: block; height: 130px; margin: 0px auto; width: 434px;"></p> + +<p>Avec l'attribut {{htmlattrxref("multiple","input")}}, l'utilisateur pourra saisir plusieurs adresses électroniques dans la même entrée (avec une virgule comme séparateur).</p> + +<p>Sur certains périphériques (les mobiles en particulier), un clavier virtuel différent et mieux adapté à la saisie d'adresses électroniques peut être affiché.</p> + +<div class="note"> +<p><strong>Note</strong>: Vous trouverez plus de détails sur la validation des formulaires dans l'article <a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaires</a>.</p> +</div> + +<h4 id="Champ_pour_mot_de_passe">Champ pour mot de passe</h4> + +<p>Ce type de champ est défini en donnant la valeur <code>password</code> à l'attribut {{htmlattrxref("type","input")}} :</p> + +<pre class="brush: html"> <input type="password" id="pwd" name="pwd"></pre> + +<p>Aucune contrainte de saisie du texte n'est ajoutée, mais la valeur entrée dans le champ est masquée (avec des points ou des astérisques) afin qu'elle ne puisse pas être lue par d'autres.</p> + +<p>Gardez à l'esprit que ceci n'est qu'une fonction de l'interface utilisateur ; sauf si vous soumettez le formulaire de manière sécurisée, il sera envoyé en texte brut, ce qui est mauvais pour la sécurité — un tiers malicieux pourrait intercepter les données et voler le mot de passe, les détails de la carte de crédit ou autre texte soumis. La meilleure façon de protéger l'utilisateur contre ceci consiste à héberger toute page contenant des formulaires avec une connexion sécurisée (par ex. avec https:// ...), ainsi les données sont chiffrées avant expédition.</p> + +<p>Les navigateurs modernes reconnaissent les risques courus lors de l'envoi de formulaires avec une connexion non sécurisée et affichent des avertissements pour prévenir les utilisateurs. Pour plus de précisions sur ce que Firefox a mis en œuvre, voir <a href="/fr/docs/Sécurité/MotsdepasseInsecurisés">Mots de passe peu sûrs</a>.</p> + +<h4 id="Champ_de_recherche">Champ de recherche</h4> + +<p>Ce type de champ se définit avec la valeur <code>search</code> de l'attribut {{htmlattrxref("type","input")}} :</p> + +<pre class="brush: html"> <input type="search" id="search" name="search"></pre> + +<p>La principale différence entre un champ textuel et un champ de recherche est dans l'apparence — souvent, les champs de recherche sont affichés avec des coins arrondis, et/ou avec une « × » à cliquer pour effacer la valeur entrée. Toutefois, une fonction est aussi ajoutée : les valeurs saisies peuvent être automatiquement enregistrées afin d'être utilisées pour compléter des recherches sur plusieurs pages du même site.</p> + +<p><img alt="Screenshots of search fields on several platforms." src="/files/4269/all-search-field.png" style="height: 235px; width: 655px;"></p> + +<h4 id="Champ_pour_numéro_de_téléphone">Champ pour numéro de téléphone</h4> + +<p>Ce type de champ se définit en donnant la valeur <code>tel</code> à l'attribut {{htmlattrxref("type","input")}} :</p> + +<pre class="brush: html"> <input type="tel" id="tel" name="tel"></pre> + +<p>À cause de la grande variété de formats de numéros de téléphones à travers le monde, ce type de champ n'ajoute pas de contrainte à la valeur saisie par l'utilisateur. C'est principalement une différence sémantique, bien que sur certains appareils (notamment mobiles) un clavier virtuel différent, mieux adapté à la saisie de numéros de téléphone, puisse être présenté.</p> + +<h4 id="Champ_dURL">Champ d'URL</h4> + +<p>Ce type de champ se définit en donnant la valeur <code>url</code> à l'attribut {{htmlattrxref("type","input")}} :</p> + +<pre class="brush: html"> <input type="url" id="url" name="url"></pre> + +<p>Il ajoute une contrainte de validation spéciale du champ ; le navigateur renvoie une erreur si une URL invalide est saisie.</p> + +<div class="note"><strong>Note :</strong> ce n'est pas parce qu'une URL est bien formée qu'elle pointe vers un emplacement qui existe réellement.</div> + +<div class="note"> +<p><strong>Note :</strong> La présence de champs avec contraintes spéciales considérés comme erronés bloquent l'envoi du formulaire. De plus, leur apparence peut être adaptée afin de mettre en évidence l'erreur. Nous allons discuter de cela dans l'article <a href="/fr/docs/HTML/Formulaires/Validation_de_formulaires" title="/fr/docs/HTML/Formulaires/Validation_de_formulaire">Validation de formulaires</a>.</p> +</div> + +<h3 id="Champs_texte_multilignes">Champs texte multilignes</h3> + +<p>Un champ texte sur plusieurs lignes se définit avec l'élément {{HTMLElement("textarea")}}, et non avec l'élément {{HTMLElement("input")}}.</p> + +<pre class="brush: html"> <textarea cols="30" rows="10"></textarea></pre> + +<p>La principale différence entre un champ <code>textarea</code> et un champ monoligne est que, dans un textarea, l'utilisateur peut saisir du texte avec des sauts de ligne en dur (c'est à dire en pressant la touche <code>Retour</code>).</p> + +<p><img alt="Screenshots of multi-lines text fields on several platforms." src="/files/4271/all-multi-lines-text-field.png" style="height: 330px; width: 745px;"></p> + +<div class="note"> +<p><strong>Note :</strong> Vous trouverez un exemple de champ texte multiligne sur GitHub à l'adresse <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/multi-line-text-field.html">multi-line-text-field.html</a> (voir aussi <a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/multi-line-text-field.html">directement</a>). Jetez-y un coup d'œil, et remarquez que dans la plupart des navigateurs, la zone de texte est dotée d'une poignée d'étirement en bas à droite pour permettre à l'utilisateur de la redimensionner. Cette capacité de redimensionnement peut être désactivée en réglant la propriété {{cssxref("resize")}} de la zone de texte à <code>none</code> dans les CSS.</p> +</div> + +<p>{{htmlelement("textarea")}} accepte également quelques attributs pour contrôler son rendu sur plusieurs lignes (outre plusieurs autres) :</p> + +<table> + <caption>Attributs pour l'élément {{HTMLElement("textarea")}}</caption> + <thead> + <tr> + <th scope="col">Nom de l'attribut</th> + <th scope="col">Valeur par défaut</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{htmlattrxref("cols","textarea")}}</td> + <td><code>20</code></td> + <td>Largeur visible de la boîte de contrôle texte, mesurée en largeurs de caractères.</td> + </tr> + <tr> + <td>{{htmlattrxref("rows","textarea")}}</td> + <td></td> + <td>Nombre de lignes de texte visibles dans la boîte de contrôle.</td> + </tr> + <tr> + <td>{{htmlattrxref("wrap","textarea")}}</td> + <td><code>soft</code></td> + <td>Indique comment le contrôle va à la ligne. Les valeurs possibles sont : <code>hard</code> ou <code>soft</code></td> + </tr> + </tbody> +</table> + +<p>Notez que l'élément {{HTMLElement("textarea")}} est écrit un peu différemment de l'élément {{HTMLElement("input")}}. Ce dernier est un élément vide, ce qui signifie qu'il ne peut pas contenir d'élément enfant. A contrario, l'élément {{HTMLElement("textarea")}} est un élément régulier pouvant contenir des enfants contenus de texte.</p> + +<p>Deux points clés à noter ici :</p> + +<ul> + <li>Si vous voulez définir une valeur par défaut pour un élément {{HTMLElement("input")}}, vous devez utiliser l'attribut <code>value</code> ; avec un élément {{HTMLElement("textarea")}} mettez le texte par défaut entre la balise ouvrante et la balise fermante du dit élément.</li> + <li>Par nature, l'élément {{HTMLElement("textarea")}} n'accept que des contenus textuels ; ce qui signifie que si du contenu HTML est placé dans un élément {{HTMLElement("textarea")}} il sera restitué sous forme de texte brut.</li> +</ul> + +<h2 id="Contenu_déroulant">Contenu déroulant</h2> + +<p>Les widgets déroulants sont une manière simple de permettre à l'utilisateur de choisir une option parmi plusieurs sans que cela prenne trop de place dans l'interface utilisateur. HTML dispose de deux types de contenus déroulants la <strong>boîte à sélections</strong> et la <strong>boîte à complétement automatique</strong>. Dans les deux cas l'interation est identique. Une fois le contrôle activé, le navigateur affiche une liste de valeurs ouverte au choix de l'utilisateur.</p> + +<h3 id="Boîte_à_sélection">Boîte à sélection</h3> + +<p>Une boîte à sélection est créée avec l'élément {{HTMLElement("select")}} complétée d'un ou plusieurs éléments enfants {{HTMLElement("option")}} définissant les valeurs possibles.</p> + +<pre class="brush: html"> <select> + <option>Banane</option> + <option>Cerise</option> + <option>Citron</option> + </select></pre> + +<p>Si nécessaire, la valeur par défaut de la boîte de sélection peut être définie en utilisant l'attribut {{htmlattrxref("selected","option")}} dans l'élément {{HTMLElement("option")}} désiré. Les éléments {{HTMLElement("option")}} peuvent être imbriqués dans des éléments {{HTMLElement("optgroup")}} pour créer des groupes de valeurs associées :</p> + +<pre class="brush: html"> <select> + <optgroup label="Fruits"> + <option>Banane</option> + <option selected>Cerise</option> + <option>Citron</option> + </optgroup> + <optgroup label="Légumes"> + <option>Carotte</option> + <option>Aubergine</option> + <option>Pomme de terre</option> + </optgroup> + </select></pre> + +<p><img alt="Screenshots of single line select box on several platforms." src="/files/4517/all-select.png" style="height: 636px; width: 887px;"></p> + +<p>Si un élément {{HTMLElement("option")}} est défini avec l'attribut <code>value</code>, la valeur de cet attribut est envoyée lorsque le formulaire est soumis. Si l'attribut <code>value</code> est omis, le contenu de l'élément {{HTMLElement("option")}} est utilisé comme valeur de la boîte de sélection.</p> + +<p>Sur l'élément {{HTMLElement("optgroup")}}, l'attribut <code>label</code> est affiché avant les valeurs, mais même s'il ressemble un peu à une option, il n'est pas sélectionnable.</p> + +<h3 id="Boîte_à_sélections_multiples">Boîte à sélections multiples</h3> + +<p>Par défaut, une boîte de sélection ne permet à l'utilisateur de ne sélectionner qu'une seule valeur. En ajoutant l'attribut {{htmlattrxref("multiple","select")}} à l'élément {{HTMLElement("select")}}, l'utilisateur peut sélectionner plusieurs valeurs en utilisant le mécanisme par défaut du système d'exploitation (par ex. en pressant <kbd>Cmd</kbd>/<kbd>Ctrl</kbd> et en cliquant sur plusieur valeurs).</p> + +<p>Dans ce cas toutefois, la boîte d'utilisateur n'affiche plus les valeurs sous forme d'un menu déroulant. Les valeurs sont toutes affichées dans une liste.</p> + +<pre class="brush: html"> <select multiple> + <option>Banane</option> + <option>Cerise</option> + <option>Citron</option> + </select></pre> + +<p><img alt="Screenshots of multi-lines select box on several platforms." src="/files/4559/all-multi-lines-select.png" style="height: 531px; width: 734px;"></p> + +<div class="note"><strong>Note :</strong> tous les navigateurs prenant en charge l'élément {{HTMLElement("select")}} prennent aussi en charge l'attribut {{htmlattrxref("multiple","select")}} sur lui.</div> + +<h3 id="Contenus_auto-complétés">Contenus auto-complétés</h3> + +<p>Vous pouvez suggérer des valeurs d'auto-complémentation pour les widgets avec un élément {{HTMLElement("datalist")}} accompagné d'éléments enfants {{HTMLElement("option")}} précisant les valeurs à afficher.</p> + +<p>La liste de données est alors liée à un champ texte (généralement un élément <code>input</code>) avec l'attribut {{htmlattrxref("list","input")}}.</p> + +<p>Une fois la liste de données affiliée au widget de formulaire, ses options s'utilisent comme complémentation du texte saisi par l'utilisateur ; cela se présente généralement à l'utilisateur sous forme d'une boîte déroulante listant des correspondances possibles avec ce qui doit être saisi dans la boîte.</p> + +<pre class="brush: html"> <label for="onFruit">Quel est votre fruit préféré ?</label> + <input type="text" id="onFruit" list="maSuggestion" /> + <datalist id="maSuggestion"> + <option>Pomme</option> + <option>Banane</option> + <option>Mûre</option> + <option>Airelles</option> + <option>Citron</option> + <option>Litchi</option> + <option>Pêche</option> + <option>Poire</option> + </datalist></pre> + +<div class="note"><strong>Note :</strong> Selon la <a href="http://www.w3.org/TR/html5/common-input-element-attributes.html#attr-input-list" rel="external" title="http://www.w3.org/TR/html5/common-input-element-attributes.html#attr-input-list">norme HTML</a>, l'attribut {{htmlattrxref("list","input")}} et l'élément {{HTMLElement("datalist")}} peuvent s'utiliser avec tout type de widget nécessitant une saisie utilisateur. Toutefois, les modalités de ce fonctionnement ne sont pas claire pour des contrôles autres que textuels (de couleur ou de date par ex.) et les divers navigateurs se comporteront de manière différente selon le cas. Pour cette raison, soyez prudent en utilisant cette fonctionnalité avec autre chose que des champs textuels.</div> + +<div><img alt="Screenshots of datalist on several platforms." src="/files/4593/all-datalist.png" style="height: 329px; width: 437px;"></div> + +<div> +<h4 id="Prise_en_charge_de_Datalist_et_recours">Prise en charge de Datalist et recours</h4> + +<p>L'élément {{HTMLElement("datalist")}} est un ajout très récent aux formulaires HTML, donc sa prise en charge par les navigateurs est un peu plus limitée que ce que nous avons vu précédemment. En particulier, il n'est pas pris en charge dans les versions d'IE inférieures à 10, et Safari ne le prend toujours pas en charge au moment de la rédaction de cet article.</p> + +<p>Pour gérer cela, voici une petite astuce offrant une bonne solution de repli pour ces navigateurs :</p> + +<pre class="brush:html; line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>myFruit<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Quel est votre fruit préféré ? (avec repli)<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>text<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>myFruit<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>fruit<span class="punctuation token">"</span></span> <span class="attr-name token">list</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>fruitList<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>datalist</span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>fruitList<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>suggestion<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>ou choisissez un fruit<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>select</span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>suggestion<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>altFruit<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Pomme<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Banane<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Mûres<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Airelles<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Citron<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Litchi<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Pêche<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Poire<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>select</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>datalist</span><span class="punctuation token">></span></span></code></pre> + +<p>Les navigateurs qui prennent en charge l'élément {{HTMLElement("datalist")}} ignoreront tous les éléments qui ne sont pas {{HTMLElement("option")}} et fonctionneront comme prévu. D'autre part, les navigateurs qui ne prennent pas en charge l'élément {{HTMLElement("datalist")}} afficheront l'étiquette et la boîte de sélection. Bien sûr, il y a d'autres façons de gérer ce manque de prise en charge de l'élément {{HTMLElement("datalist")}}, mais c'est la manière la plus simple (d'autres ont besoin de JavaScript).</p> + +<table> + <tbody> + <tr> + <th scope="row">Safari 6</th> + <td><img alt="Screenshot of the datalist element fallback with Safari on Mac OS" src="https://developer.mozilla.org/files/4583/datalist-safari.png" style="height: 32px; width: 495px;"></td> + </tr> + <tr> + <th scope="row">Firefox 18</th> + <td><img alt="Screenshot of the datalist element with Firefox on Mac OS" src="https://developer.mozilla.org/files/4581/datalist-firefox-macos.png" style="height: 102px; width: 353px;"></td> + </tr> + </tbody> +</table> +</div> + +<h2 id="Éléments_à_cocher">Éléments à cocher</h2> + +<p>Les éléments à cocher sont des widgets dont l'état se modifie en cliquant sur eux. Il existe deux types d'éléments à cocher : la case à cocher et le bouton radio. Les deux utilisent l'attribut {{htmlattrxref("checked","input")}} pour indiquer si le widget est coché par défaut ou non.</p> + +<p>Il est important de noter que ces widgets ne se comportent pas tout à fait comme les autres widgets de formulaires. Pour la plupart des widgets, une fois que le formulaire est envoyé, tous les widgets dont l'attribut {{htmlattrxref("name","input")}} est défini sont envoyés, même s'ils ne sont pas renseignés. Dans le cas des éléments à cocher, leurs valeurs ne sont envoyées que s'ils sont cochés. S'ils ne sont pas cochés, rien n'est envoyé, pas même la valeur de leur attribut <code>name</code>.</p> + +<div class="note"> +<p><strong>Note</strong> : Vous trouverez les exemples de cette section sur GitHub à l'adresse <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/checkable-items.html">checkable-items.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/checkable-items.html">voir directement aussi</a>).</p> +</div> + +<p>Pour un maximum de convivialité/accessibilité, il est conseillé d'entourer chaque liste d'éléments liés dans un {{htmlelement("fieldset")}}, avec un élément {{htmlelement("legend")}} fournissant une description globale de la liste. Chaque paire individuelle d'éléments {{htmlelement("label")}}/{{htmlelement("input")}} doit être contenue dans son propre élément de liste (ou similaire), comme le montrent les exemples.</p> + +<p>Vous devez également fournir des valeurs pour ces types d'entrées dans l'attribut <code>value</code> si vous voulez qu'elles aient un sens — si aucune valeur n'est fournie, les cases à cocher et les boutons radio ont la valeur <code>on</code>.</p> + +<h3 id="Case_à_cocher">Case à cocher</h3> + +<p>Une casce à cocher se crée avec l'élément {{HTMLElement("input")}} dont l'attribut {{htmlattrxref("type","input")}} a pour valeur <code>checkbox</code>.</p> + +<pre class="brush: html"> <input type="checkbox" <code class="language-html"><span class="tag token"><span class="attr-name token">checked</span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>carrots<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>carrots<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>carrots<span class="punctuation token">"</span></span></span></code>> +</pre> + +<p>Mettre l'attribut <code>checked</code> fait que la case sera cochée au chargement de la page.</p> + +<p><img alt="Screenshots of check boxes on several platforms." src="/files/4595/all-checkbox.png" style="height: 198px; width: 352px;"></p> + +<h3 id="Bouton_radio">Bouton radio</h3> + +<p>Un bouton radio se crée avec un élément {{HTMLElement("input")}} dont l'attribut {{htmlattrxref("type","input")}} a la valeur <code>radio</code>.</p> + +<pre class="brush: html"> <input type="radio" checked<code class="language-html"><span class="tag token"><span class="attr-name token"> id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>soup<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>meal<span class="punctuation token">"</span></span></span></code>></pre> + +<p>Plusieurs boutons radio peuvent être liés ensemble. S'ils partagent la même valeur pour leur attribut {{htmlattrxref("name","input")}}, ils seront considérés comme faisant partie d'un seul groupe de boutons. Seulement un bouton à la fois peut être coché par groupe. Ceci signifie que si l'un d'entre eux est coché, tous les autres sont automatiquement décochés. Lorsque le formulaire est envoyé, seule la valeur du bouton coché est envoyée. Si aucun des boutons n'est coché, l'ensemble des boutons du groupe est considéré comme étant dans un état inconnu et aucune valeur n'est envoyée avec le formulaire.</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><fieldset> + <legend>Quel est votre mets préféré ?</legend> + <ul> + <li> + <label for="soup">Soupe</label> + <input type="radio" checked id="soup" name="meal" value="soup"> + </li> + <li> + <label for="curry">Curry</label> + <input type="radio" id="curry" name="meal" value="curry"> + </li> + <li> + <label for="pizza">Pizza</label> + <input type="radio" id="pizza" name="meal" value="pizza"> + </li> + </ul> +</fieldset></code></pre> + +<p><img alt="Screenshots of radio buttons on several platforms." src="/files/4597/all-radio.png" style="height: 198px; width: 352px;"></p> + +<h2 id="Boutons">Boutons</h2> + +<p>Dans les formulaires HTML, il existe trois types de boutons :</p> + +<dl> + <dt>Submit</dt> + <dd>Envoie les données du formulaire au serveur.</dd> + <dt>Reset</dt> + <dd>Réinitialise les widgets de formulaire à leurs valeurs par défaut.</dd> + <dt>Anonymous</dt> + <dd>Type de bouton n'ayant pas d'effet prédéfini mais qui peut être personnalisé grâce à du code JavaScript.</dd> +</dl> + +<p>Un bouton se crée avec un élément {{HTMLElement("button")}} ou un élément {{HTMLElement("input")}}. C'est la valeur de l'attribut {{htmlattrxref("type","input")}} qui définit le type de bouton affiché :</p> + +<h3 id="submit">submit</h3> + +<pre class="brush: html"> <button type="submit"> + Ceci est un <br><strong>bouton d'envoi</strong> + </button> + + <input type="submit" value="Ceci est un bouton d'envoi"></pre> + +<h3 id="reset">reset</h3> + +<pre class="brush: html"> <button type="reset"> + Ceci est un <br><strong>bouton de réinitialisation</strong> + </button> + + <input type="reset" value="Ceci est un bouton de réinitialisation"></pre> + +<h3 id="anonymous">anonymous</h3> + +<pre class="brush: html"> <button type="button"> + Ceci est un <br><strong>bouton lambda</strong> + </button> + + <input type="button" value="Ceci est un bouton lambda"></pre> + +<p>Les boutons se comportent de la même manière que vous utilisiez l'élément {{HTMLElement("button")}} ou l'élément {{HTMLElement("input")}}. Il existe toutefois quelques différences à noter :</p> + +<ul> + <li>Comme on peut le voir dans l'exemple précédent, les éléments {{HTMLElement("button")}} autorisent l'utilisation de contenu HTML dans l'étiquette, tandis que les éléments {{HTMLElement("input")}} n'acceptent que du texte brut.</li> + <li>Dans le cas des éléments {{HTMLElement("button")}}, il est possible d'avoir une valeur différente de l'étiquette du bouton (toutefois, ceci ne peut être utilisé pour les versions antérieures à la version 8 d'Internet Explorer).</li> +</ul> + +<p><img alt="Screenshots of buttons on several platforms." src="/files/4599/all-buttons.png" style="height: 235px; width: 464px;"></p> + +<p>Techniquement parlant, il n'y a pratiquement pas de différence entre un bouton défini avec l'élément {{HTMLElement("button")}} ou l'élément {{HTMLElement("input")}}. La seule différence à noter réside dans l'étiquette du bouton lui-même. Dans un élément {{HTMLElement("input")}}, l'étiquette ne peut être constituée que de données de type caractère, alors que dans un élément {{HTMLElement("button")}}, l'étiquette peut être mise sous HTML, de sorte qu'elle peut être mise en forme en conséquence.</p> + +<h2 id="Widgets_de_formulaires_avancés">Widgets de formulaires avancés</h2> + +<p>Ces widgets sont des contrôles permettant l'utilisateur de saisir des données plus complexes ou moins habituelles, comme des nombres exacts ou approchés, des dates et heures ainsi que des couleurs.</p> + +<h3 id="Nombres">Nombres</h3> + +<p>On crée un widget pour nombres avec un élément {{HTMLElement("input")}} dont l'attribut {{htmlattrxref("type","input")}} a pour valeur <code>number</code>. Ce contrôle ressemble à un champ texte mais il n'accepte que des chiffres en virgule flottante, et propose habituellement des boutons pour augmenter ou réduire la valeur dans le widget.</p> + +<p>Il est aussi possible de :</p> + +<ul> + <li>contraindre la valeur en définissant les attributs {{htmlattrxref("min","input")}} et {{htmlattrxref("max","input")}}.</li> + <li>définir l'incrément de modification de la valeur du widget à l'aide des boutons ad‑hoc en précisant l'attribut {{htmlattrxref("step","input")}}.</li> +</ul> + +<h4 id="Exemple">Exemple</h4> + +<pre class="brush: html"> <input type="number" <code class="language-html"><span class="tag token"><span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>age<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>age<span class="punctuation token">"</span></span></span></code> min="1" max="10" step="2"></pre> + +<p>Ceci créé un widget pour un nombre dont la valeur est comprise entre 1 et 10 et dont les boutons d'incrémentation/décrémentation modifient la valeur par pas de 2.</p> + +<h3 id="Curseurs">Curseurs</h3> + +<p>Le curseur est une autre manière de sélectionner un nombre. Comme, visuellement parlant, les curseurs sont moins précis qu'un champ textuel, ils sont utilisés pour retenir un nombre dont la précision de valeur n'est pas primordiale.</p> + +<p>Un curseur se crée avec l'élément {{HTMLElement("input")}} dont l'attribut {{htmlattrxref("type","input")}} a pour valeur <code>range</code>. Il est important de configurer convenablement le curseur. À cet effet, il est fortement recommandé de définir les attributs {{htmlattrxref("min","input")}}, {{htmlattrxref("max","input")}} et {{htmlattrxref("step","input")}}.</p> + +<h4 id="Exemple_2">Exemple</h4> + +<pre class="brush: html line-numbers language-html"> <code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>range<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>beans<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>beans<span class="punctuation token">"</span></span> <span class="attr-name token">min</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>0<span class="punctuation token">"</span></span> <span class="attr-name token">max</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>500<span class="punctuation token">"</span></span> <span class="attr-name token">step</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>10<span class="punctuation token">"</span></span><span class="punctuation token">> +</span></span></code></pre> + +<p>Cet exemple créé un curseur dont les valeurs varient entre 0 et 500, et dont les bouton d'incrément/décrément font varier la valeur de ±10.</p> + +<p>Un problème avec les curseurs est qu'il n'offrent aucun moyen visue de savoir quelle est leur valeur courante. Il est nécessaire d'ajouter cela vous‑même à l'aide de JavaScript, mais c'est assez facile. Dans cet exemple nous ajoutons un élément {{htmlelement("span")}} dans lequel nous écrivons la valeur courante du curseur et la mettons à jour quand elle est modifiée.</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>beans<span class="punctuation token">"</span></span><span class="punctuation token">>Combien de haricots pouvez‑vous manger </span></span>?<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>range<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>beans<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>beans<span class="punctuation token">"</span></span> <span class="attr-name token">min</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>0<span class="punctuation token">"</span></span> <span class="attr-name token">max</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>500<span class="punctuation token">"</span></span> <span class="attr-name token">step</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>10<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>span</span> <span class="attr-name token">class</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>beancount<span class="punctuation token">"</span></span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>span</span><span class="punctuation token">></span></span></code></pre> + +<p>et en JavaScript :</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">var</span> beans <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">querySelector</span><span class="punctuation token">(</span><span class="string token">'#beans'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="keyword token">var</span> count <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">querySelector</span><span class="punctuation token">(</span><span class="string token">'.beancount'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + +count<span class="punctuation token">.</span>textContent <span class="operator token">=</span> beans<span class="punctuation token">.</span>value<span class="punctuation token">;</span> + +beans<span class="punctuation token">.</span>oninput <span class="operator token">=</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> + count<span class="punctuation token">.</span>textContent <span class="operator token">=</span> beans<span class="punctuation token">.</span>value<span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<p>Ici nous stockons dans deux variables les références du curseur et celle de <code>span</code>, puis nous réglons immédiatement le <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent">textContent</a></code> de <code>span</code> à la valeur courante <code>value</code> de l'entrée. Enfin, nous avons mis en place un gestionnaire d'événements oninput de sorte que chaque fois que le curseur de plage est déplacé, le <code>textContent</code> de <code>span</code> est mis à jour avec la nouvelle valeur de l'entrée.</p> + +<p>L'attribut <code>range</code> pour <code>input</code> n'est pas pris en charge dans les versions d'Internet Explorer dont le numéro est inférieur à 10.</p> + +<h3 id="Sélection_de_date_et_heure">Sélection de date et heure</h3> + +<p>Recueillir des données de date et heure a traditionnellement toujours été un cauchemar pour les développeurs web. HTML5 ajoute des améliorations en ajoutant un contrôle qui permet de manipuler ce type de données.</p> + +<p>Un contrôle de sélection de date et heure se crée avec l'élément {{HTMLElement("input")}} et une valeur appropriée de l'attribut {{htmlattrxref("type","input")}} selon que vous voulez recueillir des dates, des heures ou les deux.</p> + +<h4 id="datetime-local"><code>datetime-local</code></h4> + +<p>Cette valeur d'attribut créé un widget pour afficher et sélectionner une date et une heure quelque soit le fuseau horaire.</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><input type="datetime-local" name="datetime" id="datetime"></code></pre> + +<h4 id="month"><code>month</code></h4> + +<p>Cette valeur d'attribut créé un widget pour afficher et sélectionner un mois dans une année donnée.</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><input type="month" name="month" id="month"></code></pre> + +<h4 id="time"><code>time</code></h4> + +<p>Cette valeur d'attribut créé un widget pour afficher et sélectionner un horaire.</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><input type="time" name="time" id="time"></code></pre> + +<h4 id="week"><code>week</code></h4> + +<p>Cette valeur d'attribut crée un widget pour afficher et sélectionner une semaine et l'année correspondante.</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><input type="week" name="week" id="week"></code></pre> + +<p>Tous les contrôles de sélection de date et heure peuvent être contraints à l'aide des attributs {{htmlattrxref("min","input")}} et {{htmlattrxref("max","input")}}.</p> + +<pre class="brush: html"> <label for="maDate">Quand êtes vous disponible cet été ?</label> + <input type="date" min="2013-06-01" max="2013-08-31" id="maDate"></pre> + +<p class="warning"><strong>Attention :</strong> Les widgets de date et heure sont encore peu pris en charge. Au moment de la rédaction de cet article, Chrome, Edge et Opera les prennent bien en charge, mais il n'y a pas de prise en charge dans Internet Explorer et Firefox et Safari n'ont qu'une prise en charge lacunaire de ces derniers.</p> + +<h3 id="Sélecteur_de_couleur">Sélecteur de couleur</h3> + +<p>Les couleurs sont toujours compliquées à manier. Il existe plusieurs façons de les exprimer : valeurs RGB (décimale ou hexadécimale), valeurs HSL, mots-clés, etc. Les widgets de sélection de couleur permettent aux utilisateurs de sélectionner une couleur dans un contexte textuel et visuel.</p> + +<p>Un widget de sélection de couleur se crée avec un élément {{HTMLElement("input")}} dont l'attribut {{htmlattrxref("type","input")}} a pour valeur <code>color</code>.</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>color<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>color<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>color<span class="punctuation token">"</span></span><span class="punctuation token">></span></span></code></pre> + +<p>Attention : la prise en charge du widget <code>color</code> n'est pas très bonne actuellement. Il n'y a aucune prise en charge dans Internet Explorer, ni actuellement dans Safari. Les autres navigateurs majeurs le prennent en charge.</p> + +<h2 id="Autres_widgets">Autres widgets</h2> + +<p>Il existe d'autres types de widgets qui ne peuvent pas être classés facilement à cause de leur comportement très particulier, mais qui sont toujours très utiles.</p> + +<div class="note"> +<p id="Sélection_de_fichier"><strong>Note </strong>: Vous trouverez les exemples de cette section sur GitHub à l'adresse <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/other-examples.html">other-examples.html</a> (à voir aussi<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/other-examples.html"> directement</a>).</p> +</div> + +<h3 id="Sélection_de_fichier_2">Sélection de fichier</h3> + +<p>Les formulaires HTML permettent d'envoyer des fichiers à un serveur. Cette action spécifique est détaillée dans l'article « <a href="https://developer.mozilla.org/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires" title="/fr/docs/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi et extraction des données de formulaire</a> ». Le widget de sélection de fichier permet à l'utilisateur de choisir un ou plusieurs fichiers à envoyer.</p> + +<p>Pour créer un widget de sélection de fichier, vous devez utiliser un élément {{HTMLElement("input")}} dont l'attribut {{htmlattrxref("type","input")}} a pour valeur <code>file</code>. Les types de fichiers acceptés peuvent être contraints en utilisant l'attribut {{htmlattrxref("accept","input")}}. De plus, si vous souhaitez permettre à l'utilisateur de choisir plusieurs fichiers, vous pouvez le faire en ajoutant l'attribut {{htmlattrxref("multiple","input")}}.</p> + +<h4 id="Exemple_3">Exemple</h4> + +<p>Dans cet exemple, le widget de sélection de fichiers permet de sélectionner des fichiers d'images. L'utilisateur peut sélectionner plusieurs fichiers.</p> + +<pre class="brush: html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>file<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>file<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>file<span class="punctuation token">"</span></span> <span class="attr-name token">accept</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>image/*<span class="punctuation token">"</span></span> <span class="attr-name token">multiple</span><span class="punctuation token">></span></span></code></pre> + +<h3 id="Contenu_caché">Contenu caché</h3> + +<p>Il est parfois pratique pour des raisons techniques d'avoir des morceaux d'informations qui soient envoyés au serveur sans être montrées à l'utilisateur. Pour ce faire, vous pouvez ajouter un élément invisible dans votre formulaire. Cela est possible en utilisant un élément {{HTMLElement("input")}} dont l'attribut {{htmlattrxref("type","input")}} a pour valeur <code>hidden</code>.</p> + +<p>Si vous créez un tel élément, il est obligatoire de définir ses attributs <code>name</code> et <code>value</code> :</p> + +<pre class="brush: html"> <input type="hidden" <code class="language-html"><span class="tag token"><span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>timestamp<span class="punctuation token">"</span></span> </span></code>name="timestamp" value="1286705410"></pre> + +<h3 id="Image-bouton">Image-bouton</h3> + +<p>Le contrôle <strong>image-bouton</strong> est affiché comme un élément {{HTMLElement("img")}}, à la différence que lorsque l'utilisateur clique dessus, il se comporte comme un bouton d'envoi (voir ci-dessus).</p> + +<p>Une image-bouton se crée avec un élément {{HTMLElement("input")}} dont l'attribut {{htmlattrxref("type","input")}} a pour valeur <code>image</code>. Cet élément accepte exactement le même ensemble d'attributs que l'élément {{HTMLElement("img")}}, en plus de tous les attributs valides pour n'importe quel bouton de formulaire.</p> + +<pre class="brush: html"> <input type="image" alt="Click me!" src="my-img.png" width="80" height="30" /></pre> + +<p>Si l'image-bouton est utilisée pour envoyer un formulaire, ce widget n'envoie pas sa valeur mais les coordonnées X et Y du clic sur l'image (les coordonnées sont relatives à l'image, ce qui veut dire que le coin supérieur gauche représente les coordonnées 0, 0). Les coordonnées sont envoyées sous la forme de deux paires de clé/valeur :</p> + +<ul> + <li>la valeur X est la valeur de l'attribut {{htmlattrxref("name","input")}} suivie de la chaîne « <em>.x</em> »</li> + <li>la valeur Y est la valeur de l'attribut {{htmlattrxref("name","input")}} suivie de la chaîne « <em>.y</em> ».</li> +</ul> + +<p>Lorsque vous cliquez sur l'image dans ce formulaire, vous êtes redirigés une URL du type suivant :</p> + +<pre> http://foo.com?pos.x=123&pos.y=456</pre> + +<p>C'est une façon très commode de construire une « hot map » (cartographie des parties d'une page Internet le plus souvent balayées par le regard des lecteurs). La manière d'envoyer et d'extraire ces valeurs est détaillée dans l'article <span>« </span><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires" title="/fr/docs/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires"><span>Envoi des données de formulaire</span></a> ».</p> + +<h3 id="Compteurs_et_barres_de_progression">Compteurs et barres de progression</h3> + +<p>Les compteurs et barres de progressions sont des représentations visuelles de valeurs numériques.</p> + +<h4 id="Progress">Progress</h4> + +<p>Une barre de progression représente une valeur qui évolue dans le temps jusqu'à une valeur maximale définie par l'attribut {{htmlattrxref("max","progress")}}. Une telle barre peut être créée grace à un élément {{ HTMLElement("progress")}}.</p> + +<pre class="brush: html"> <progress max="100" value="75">75/100</progress></pre> + +<p>Cela sert à mettre en œuvre visuellement un rapport d'avancement, comme le pourcentage du nombre total de fichiers téléchargés ou le nombre de questions posées dans un questionnaire.</p> + +<p>Le contenu dans l'élément {{HTMLElement("progress")}} est un affichage informatif de repli pour les navigateurs ne prenant pas en charge cet élément ; les technologies d'assistance vocalisent ce contenu.</p> + +<h4 id="Meter">Meter</h4> + +<p>Un étalon est une valeur fixe dans une plage délimitée par une valeur minimale {{htmlattrxref("min","meter")}} et une valeur maximale {{htmlattrxref("max","meter")}}. Cette valeur est affichée dans une barre, et pour savoir à quoi cette barre ressemble, nous comparons certaines valeurs :</p> + +<ul> + <li>les valeurs {{htmlattrxref("low","meter")}} et {{htmlattrxref("high","meter")}} divisent l'intervalle en trois parties : + <ul> + <li>la partie basse de l'intervalle est comprise entre les valeurs {{htmlattrxref("min","meter")}} et {{htmlattrxref("low","meter")}} (les deux valeurs sont incluses)</li> + <li>la partie médiane de l'intervalle est comprise entre les valeurs {{htmlattrxref("low","meter")}} et {{htmlattrxref("high","meter")}} (les deux valeurs sont exclues)</li> + <li>la partie haute de l'intervalle est comprise entre les valeurs {{htmlattrxref("high","meter")}} et {{htmlattrxref("max","meter")}} (les deux valeurs sont incluses)</li> + </ul> + </li> + <li>La valeur {{htmlattrxref("optimum","meter")}} définit la valeur optimale pour l'élément {{HTMLElement("meter")}}. En conjonction avec les valeurs {{htmlattrxref("low","meter")}} et {{htmlattrxref("high","meter")}}, elle définit quelle partie de la plage est préféré : + <ul> + <li>Si la valeur {{htmlattrxref("optimum","meter")}} est dans la partie basse de l'intervalle, la partie basse est considérée comme la partie préférée, la partie médiane est considérée comme la partie moyenne et la partie haute comme la moins favorable.</li> + <li>Si la valeur {{htmlattrxref("optimum","meter")}} est dans la partie médiane, la partie basse est considérée comme la partie moyenne, la partie médiane comme la partie préférée et la partie haute comme moyenne également.</li> + <li>Si la valeur {{htmlattrxref("optimum","meter")}} est dans la partie haute, la partie basse est considérée comme la moins favorable, la partie médiane comme moyenne et la partie haute comme la partie préférée.</li> + </ul> + </li> +</ul> + +<p>Tous les navigateurs compatibles avec l'élément {{HTMLElement("meter")}} utilisent ces valeurs pour modifier la couleur de la barre :</p> + +<ul> + <li>Si la valeur actuelle est dans la partie préférée, la barre est verte.</li> + <li>Si la valeur actuelle est dans la partie moyenne, la barre est jaune.</li> + <li>Si la valeut actuelle est dans la partie la moins favorable, la barre est rouge.</li> +</ul> + +<p>Une telle barre se crée avec un élément {{HTMLElement("meter")}}. Cela permet d'implémenter toute sorte d'étalonnage, par exemple une barre montrant l'espace total utilisé sur un disque, qui devient rouge si le disque commence à être plein.</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>meter</span> <span class="attr-name token">min</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>0<span class="punctuation token">"</span></span> <span class="attr-name token">max</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>100<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>75<span class="punctuation token">"</span></span> <span class="attr-name token">low</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>33<span class="punctuation token">"</span></span> <span class="attr-name token">high</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>66<span class="punctuation token">"</span></span> <span class="attr-name token">optimum</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>50<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>75<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>meter</span><span class="punctuation token">></span></span></code></pre> + +<p>Le contenu de l'élément {{HTMLElement("meter")}} est un affichage informatif de repli pour les navigateurs ne prenant pas en charge cet élément ; les technologies d'assistance vocalisent cet affichage.</p> + +<p>La prise en charge de <code>progress</code> et <code>meter</code> est vraiment bonne — il n'y a pas de prise en charge dans Internet Explorer, mais les autres navigateurs l'acceptent bien.</p> + +<h2 id="Conclusion">Conclusion</h2> + +<p>Comme nous venons de le voir, il y a pas mal d'éléments de formulaire différents disponibles — il n'est pas nécessaire de mémoriser l'ensemble de ces détails dès maintenant, mais vous pourrez revenir à cet article tant que vous le voudrez pour revoir tel ou tel détail.</p> + +<h2 id="Voir_également">Voir également</h2> + +<p>Pour entrer plus en détails des différents widgets de formulaires, voici quelques ressources externes très utiles que vous pouvez visiter :</p> + +<ul> + <li><a href="http://wufoo.com/html5/" rel="external" title="http://wufoo.com/html5/">L'état actuelle des formulaires HTML5</a> par Wufoo (en anglais)</li> + <li><a href="http://www.quirksmode.org/html5/inputs.html" rel="external" title="http://www.quirksmode.org/html5/inputs.html">Tests HTML5 - inputs</a> sur Quirksmode (en anglais) (et <a href="http://www.quirksmode.org/html5/inputs_mobile.html" rel="external" title="http://www.quirksmode.org/html5/inputs_mobile.html">pour les navigateurs mobiles</a>)</li> +</ul> + +<p>{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML", "Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires", "Web/Guide/HTML/Formulaires")}}</p> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML">Mon premier formulaire HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML"><span>Comment structurer un formulaire HTML</span></a></li> + <li>Les widgets natifs pour formulaire</li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets personnalisés pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">Mise en forme des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">Mise en forme avancée des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Table de compatibilité des propriétés pour les widgets de formulaire</a></li> +</ul> diff --git a/files/fr/web/guide/html/formulaires/mon_premier_formulaire_html/exemple/index.html b/files/fr/web/guide/html/formulaires/mon_premier_formulaire_html/exemple/index.html new file mode 100644 index 0000000000..3f25e6d644 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/mon_premier_formulaire_html/exemple/index.html @@ -0,0 +1,104 @@ +--- +title: Exemple +slug: Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML/Exemple +translation_of: Learn/Forms/Your_first_form/Example +--- +<p>Ceci est l'exemple pour l'article <a href="/fr/docs/HTML/Formulaires/Mon_premier_formulaire_HTML" title="/en-US/docs/HTML/Forms/My_first_HTML_form">Mon premier formulaire HTML</a>.</p> + +<h2 id="Un_formulaire_simple" name="Un_formulaire_simple">Un formulaire simple</h2> + +<h3 id="Contenu_HTML">Contenu HTML</h3> + +<pre class="brush: html"><form action="http://www.cs.tut.fi/cgi-bin/run/~jkorpela/echo.cgi" method="post"> + <div> + <label for="nom">Nom :</label> + <input type="text" id="nom" name="user_name"> + </div> + + <div> + <label for="courriel">Courriel :</label> + <input type="email" id="courriel" name="user_email"> + </div> + + <div> + <label for="message">Message :</label> + <textarea id="message" name="user_message"></textarea> + </div> + + <div class="button"> + <button type="submit">Envoyer le message</button> + </div> +</form></pre> + +<h3 id="Contenu_CSS">Contenu CSS</h3> + +<pre class="brush: css">form { + /* <code class="css comments">Pour le centrer dans la page</code> */ + margin: 0 auto; + width: 400px; + + /* <code class="css comments">Pour voir les limites du formulaire</code> */ + padding: 1em; + border: 1px solid #CCC; + border-radius: 1em; +} + +div + div { + margin-top: 1em; +} + +label { + /* <code class="css comments">Afin de s'assurer que toutes les étiquettes aient la même dimension et soient alignées correctement</code> */ + display: inline-block; + width: 90px; + text-align: right; +} + +input, textarea { + /* <code class="css comments">Afin de s'assurer que tous les champs textuels utilisent la même police</code> + <code class="css comments">Par défaut, textarea utilise une police à espacement constant */</code> + font: 1em sans-serif; + + /* <code class="css comments">Pour donner la même dimension à tous les champs textuels */</code> + width: 300px; + + -moz-box-sizing: border-box; + box-sizing: border-box; + + /* <code class="css comments">Pour harmoniser l'apparence des bordures des champs textuels */</code> + border: 1px solid #999; +} + +input:focus, textarea:focus { + /* <code class="css comments">Afin de réhausser les éléments actifs */</code> + border-color: #000; +} + +textarea { + /* <code class="css comments">Pour aligner correctement les champs multilignes et leurs étiquettes */</code> + vertical-align: top; + + /* <code class="css comments">Pour donner assez d'espace pour entrer du texte */</code> + height: 5em; + + /* <code class="css comments">Pour permettre aux utilisateurs de redimensionner un champ textuel horizontalement</code> + <code class="css comments">Cela ne marche pas avec tous les navigateurs */</code> + resize: vertical; +} + +.button { + /* <code class="css comments">Pour positionner les boutons de la même manière que les champs textuels */</code> + padding-left: 90px; /* <code class="css comments">même dimension que les étiquettes */</code> +} + +button { + /* <code class="css comments">Cette marge représente approximativement le même espace</code> + <code class="css comments">que celui entre les étiquettes et les champs textuels */</code> + margin-left: .5em; +}</pre> + +<h3 id="Résultat">Résultat</h3> + +<p>{{ EmbedLiveSample('Un_formulaire_simple', '100%', '280') }}</p> + +<p> </p> diff --git a/files/fr/web/guide/html/formulaires/mon_premier_formulaire_html/index.html b/files/fr/web/guide/html/formulaires/mon_premier_formulaire_html/index.html new file mode 100644 index 0000000000..8f082f6d81 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/mon_premier_formulaire_html/index.html @@ -0,0 +1,281 @@ +--- +title: Mon premier formulaire HTML +slug: Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML +tags: + - Apprentissage + - Codage + - Débutant + - Exemple + - Formulaires + - Guide + - HTML + - Web +translation_of: Learn/Forms/Your_first_form +--- +<p>{{LearnSidebar}}{{NextMenu("Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML", "Web/Guide/HTML/Formulaires")}}</p> + +<p class="summary">Le premier article de notre série vous offre une toute première expérience de création de formulaire en HTML, y compris sa conception, sa mise en œuvre en utilisant les bons éléments HTML, l'ajout de quelques très simples décorations avec les CSS et la façon dont les données sont envoyées à un serveur.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td>Notions concernant les ordinateurs et les <a href="/fr/Apprendre/HTML/Introduction_à_HTML">connaissances de base du HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td>Comprendre ce que sont les formulaires HTML, à quoi ils servent, comment les concevoir et quels sont les éléments de base HTML nécessaires dans les cas simples.</td> + </tr> + </tbody> +</table> + +<h2 id="Un_formulaire_HTML_quest-ce">Un formulaire HTML, qu'est-ce ?</h2> + +<p>Les formulaires HTML sont un des vecteurs principaux d'interaction entre un utilisateur et un site web ou une application. Ils permettent à l'utilisateur d'envoyer des données au site web. La plupart du temps, ces données sont envoyées à des serveurs web mais la page peut aussi les intercepter et les utiliser elle-même.</p> + +<p>Un formulaire HTML est composé d'un ou plusieurs widgets. Ceux-ci peuvent être des zones de texte (sur une seule ligne ou plusieurs lignes), des boîtes à sélection, des boutons, des cases à cocher ou des boutons radio. La plupart du temps, ces items sont associés à un libellé qui décrit leur rôle — des étiquettes correctement implémentées sont susceptibles d'informer clairement l'utilisateur normal ou mal‑voyant sur ce qu'il convient d'entrer dans le formulaire.</p> + +<p>La principale différence entre un formulaire HTML et un document HTML habituel réside dans le fait que, généralement, les données collectées par le formulaire sont envoyées vers un serveur web. Dans ce cas, vous avez besoin de mettre en place un serveur web pour récupérer ces données et les traiter. La mise en place d'un tel serveur ne fait pas partie des sujets abordés dans ce guide. Si vous souhaitez toutefois en savoir plus, voyez « <a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_donn%C3%A9es_des_formulaires">Envoi des données de formulaire</a> » plus loin dans ce module.</p> + +<h2 id="Concevoir_le_formulaire">Concevoir le formulaire</h2> + +<p>Avant de passer au code, il est souhaitable de prendre un peu de recul et accorder quelques instants de réflexion à votre formulaire. Dessiner un rapide croquis vous permettra de définir les informations que vous souhaitez demander à l'utilisateur. Du point de vue de l'expérience utilisateur, il est important de garder à l'esprit que plus vous demandez d'informations, plus vous risquez que votre utilisateur s'en aille. Restez simple et ne perdez pas votre objectif de vue : ne demandez que ce dont vous avez absolument besoin. La conception de formulaires est une phase importante de la construction d'un site internet ou d'une application. L'approche de l'expérience utilisateur de ces formulaires ne fait pas partie des objectifs de ce guide, mais si vous souhaitez approfondir ce sujet, vous pouvez lire les articles suivants :</p> + +<ul> + <li>Smashing Magazine a de très bons <a href="http://uxdesign.smashingmagazine.com/tag/forms/" rel="external">articles à propos de l'expérience utilisateur dans les formulaires</a>, mais le plus intéressant est certainement leur « <a href="http://uxdesign.smashingmagazine.com/2011/11/08/extensive-guide-web-form-usability/" rel="external">Guide complet pour des formulaires web facilement utilisables</a> ».</li> + <li>UXMatters est une ressource bien pensée avec de très bons conseils allant des <a href="http://www.uxmatters.com/mt/archives/2012/05/7-basic-best-practices-for-buttons.php" rel="external">meilleures pratiques de base</a> jusqu'à des sujets plus complexes tels que <a href="http://www.uxmatters.com/mt/archives/2010/03/pagination-in-web-forms-evaluating-the-effectiveness-of-web-forms.php">les formulaires sur plusieurs pages</a>.</li> +</ul> + +<p>Dans ce guide, nous allons concevoir un formulaire de contact simple. Posons les premières pierres.</p> + +<p><img alt="Le croquis du formulaire que l'on veut créer" src="https://mdn.mozillademos.org/files/15999/0006.png" style="border-style: solid; border-width: 1px; height: 375px; width: 400px;"></p> + +<p>Notre formulaire contiendra trois champs de texte et un bouton. Nous demandons simplement à notre utilisateur son nom, son adresse électronique et le message qu'il souhaite envoyer. En appuyant sur le bouton, le message sera envoyé au serveur web.</p> + +<h2 id="Apprentissage_actif_mise_en_œuvre_de_notre_formulaire_HTML"> Apprentissage actif : mise en œuvre de notre formulaire HTML</h2> + +<p>Très bien, nous sommes maintenant prêts à passer au HTML et à coder notre formulaire. Pour construire notre formulaire, nous aurons besoin des éléments HTML suivants : {{HTMLElement("form")}}, {{HTMLElement("label")}}, {{HTMLElement("input")}}, {{HTMLElement("textarea")}} et {{HTMLElement("button")}}.</p> + +<p>Avant de poursuivre, faites une copie locale de notre <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">simple modèle HTML</a> — vous y incorporerez votre formulaire.</p> + +<h3 id="Lélément_HTMLElementform">L'élément {{HTMLElement("form")}}</h3> + +<p>Tous les formulaires HTML débutent par un élément {{HTMLElement("form")}} comme celui-ci :</p> + +<pre class="brush:html; notranslate"><form action="/<code class="language-html">my-handling-form-page</code>" method="post"> + +</form></pre> + +<p>Cet élément définit un formulaire. C'est un élément conteneur au même titre que les éléments {{HTMLElement("div")}} ou {{HTMLElement("p")}}, mais il accepte aussi quelques attributs spécifiques afin de contrôler la manière dont il se comporte. Tous ses attributs sont optionnels mais définir au moins les attributs <code>action</code> et <code>method</code> est considéré comme de bonne pratique.</p> + +<ul> + <li>L'attribut <code>action</code> définit l'emplacement (une URL) où doivent être envoyées les données collectées par le formulaire.</li> + <li>L'attribut <code>method</code> définit la méthode HTTP utilisée pour envoyer les données (cela peut être « get » ou « post »).</li> +</ul> + +<div class="note"> +<p><strong>Note :</strong> Si vous souhaitez en savoir plus sur le fonctionnement de ces attributs, cela est détaillé dans l'article <a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_donn%C3%A9es_des_formulaires">« Envoi des données de formulaire</a> ».</p> +</div> + +<p>Pour le moment, ajoutez l'élément {{htmlelement("form")}} ci dessus dans le corps de votre HTML.</p> + +<h3 id="Les_éléments_HTMLElementlabel_HTMLElementinput_et_HTMLElementtextarea">Les éléments {{HTMLElement("label")}}, {{HTMLElement("input")}} et {{HTMLElement("textarea")}}</h3> + +<p>Notre formulaire de contact est très simple et ne contient que trois champs de texte, chacun ayant une étiquette. Le champ d'entrée pour le nom est un champ de texte sur une seule ligne, le champ pour l'adresse électronique est un champ de texte sur une ligne qui n'accepte que des adresses électroniques et enfin le champ pour le message est un champ de texte sur plusieurs lignes.</p> + +<p>En terme de code HTML, nous avons besoin de quelque chose qui ressemble à ceci pour mettre en œuvre nos widgets de formulaire.</p> + +<pre class="brush:html; notranslate"><form action="/ma-page-de-traitement" method="post"> + <div> + <label for="name">Nom :</label> + <input type="text" id="name" name="user_name"> + </div> + <div> + <label for="mail">e-mail :</label> + <input type="email" id="mail" name="user_mail"> + </div> + <div> + <label for="msg">Message :</label> + <textarea id="msg" name="user_message"></textarea> + </div> +</form></pre> + +<p>Les éléments {{HTMLElement("div")}} sont ici pour structurer notre code et rendre la mise en page plus facile (voir ci-dessous). Veuillez noter l'utilisation de l'attribut <code>for</code> sur tous les éléments {{HTMLElement("label")}}. C'est une manière formelle de lier un libellé à un élément du formulaire. Cet attribut fait référence à l'<code>id</code> de l'élément correspondant. Il y a plusieurs avantages à faire ainsi. Le plus évident de permettre à l'utilisateur de cliquer sur l'étiquette pour activer le bloc correspondant. Si vous souhaitez mieux comprendre les bénéfices de cet attribut, tout est détaillé dans cet article : <a href="/fr/docs/HTML/Formulaires/Comment_structurer_un_formulaire_HTML">Comment structurer un formulaire HTML</a>.</p> + +<p>Concernant l'élément {{HTMLElement("input")}}, l'attribut le plus important est l'attribut <code>type</code>. Ce dernier est extrêmement important puisqu'il définit le comportement de l'élément {{HTMLElement("input")}}. Il peut radicalement changer le sens de l'élément, faites-y attention. Si vous voulez en savoir plus à ce propos, vous pouvez lire l'article au sujet des <a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">widgets natifs pour formulaire</a>.</p> + +<ul> + <li>Dans notre exemple nous n'utilisons que la valeur <code>text</code> — qui est la valeur par défaut de cet attribut et représente un champ de texte basique sur une seule ligne acceptant n'importe quel type de texte.</li> + <li>Pour la deuxième entrée, nous utilisons la valeur <code>email</code> qui définit un champ de texte sur une seule ligne n'acceptant que des adresses électroniques valides. Cette dernière valeur transforme un champ basique en une sorte de champ « intelligent » qui réalise des vérifications sur les données fournies par l'utilisateur. Vous trouverez plus de détails sur la validation des formulaires dans l'article <a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a>.</li> +</ul> + +<p>Last but not least, remarquez la syntaxe de <code><input></code> vs <code><textarea></textarea></code>. C'est une des bizarreries du HTML. La balise <code><input></code> est un élément vide, ce qui signifie qu'il n'a pas besoin de balise fermante. Au contraire, {{HTMLElement("textarea")}} n'est pas un élément vide, il faut donc le fermer avec la balise fermante appropriée. Cela a un effet sur une caractéristique spécifique des formulaires HTML : la manière dont vous définissez la valeur par défaut. Pour définir une valeur par défaut d'un élément {{HTMLElement("input")}} vous devez utiliser l'attribut <code>value</code> de la manière suivante :</p> + +<pre class="brush:html; notranslate"><input type="text" value="par défaut cet élément sera renseigné avec ce texte"></pre> + +<p>A contrario, si vous souhaitez définir la valeur par défaut d'un élément {{HTMLElement("textarea")}}, il suffit simplement de mettre la valeur par défaut entre les balises ouvrantes et fermantes de l'élément {{HTMLElement("textarea")}} de la manière suivante :</p> + +<pre class="brush:html; notranslate"><textarea>par défaut cet élément sera renseigné avec ce texte</textarea></pre> + +<h3 id="Lélément_HTMLElementbutton">L'élément {{HTMLElement("button")}}</h3> + +<p>Notre formulaire est presque terminé. Il nous suffit seulement d'ajouter un bouton pour permettre à l'utilisateur de nous envoyer les données renseignées dans le formulaire. Ceci se fait simplement en ajoutant d'un élément {{HTMLElement("button")}} ; ajoutez‑le juste avant la balise fermante <code></form> :</code></p> + +<pre class="brush:html; notranslate"> <div class="button"> + <button type="submit">Envoyer le message</button> + </div> +</pre> + +<p>Comme vous le voyez l'élément {{htmlelement("button")}} accepte aussi un attribut de type — il peut prendre une des trois valeurs : <code>submit</code>, <code>reset</code> ou <code>button</code>.</p> + +<ul> + <li>Un clic sur un bouton <code>submit</code> (valeur par défaut) envoie les données du formulaire vers la page définie par l'attribut <code>action</code> de l'élément {{HTMLElement("form")}}.</li> + <li>Un clic sur un bouton <code>reset</code> réinitialise tous les widgets du formulaire à leurs valeurs par défaut immédiatement. Du point de vue de l'expérience utilisateur, utiliser un tel bouton est une mauvaise pratique.</li> + <li>Un clic sur un bouton <code>button</code> ne fait... rien ! Cela peut paraître stupide mais c'est en réalité très pratique pour concevoir des boutons personnalisés avec JavaScript.</li> +</ul> + +<div class="note"> +<p><strong>Note :</strong> Vous pouvez aussi utiliser l'élément {{HTMLElement("input")}} avec le type approprié pour produire un bouton, par exemple <code><input type="submit"></code>. Le principal avantage de {{HTMLElement("button")}} par rapport à l'élément {{HTMLElement("input")}} est que ce dernier ne permet d'utiliser que du texte comme étiquette tandis que l'élément {{HTMLElement("button")}} permet d'utiliser n'importe quel contenu HTML, autorisant ainsi des textes de bouton plus complexes et créatifs.</p> +</div> + +<h2 id="Mise_en_page_élémentaire_du_formulaire">Mise en page élémentaire du formulaire</h2> + +<p>Nous avons désormais notre formulaire HTML, et si vous le regardez dans votre navigateur préféré, vous verrez qu'il est plutôt laid.</p> + +<p><img alt="" src="/files/4049/form-no-style.png" style="height: 170px; width: 534px;"></p> + +<div class="note"> +<p><strong>Note :</strong> Si vous pensez que vous n'avez pas écrit un code HTML correct, faites la comparaison avec celui de notre exemple terminé — voyez <a href="https://github.com/mdn/learning-area/blob/master/html/forms/your-first-HTML-form/first-form.html">first-form.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/your-first-HTML-form/first-form.html"> </a>ou<a href="https://mdn.github.io/learning-area/html/forms/your-first-HTML-form/first-form.html"> également directement</a>).</p> +</div> + +<p>Les formulaires sont notoirement embêtants à présenter joliment. Apprendre la mise en page ou la décoration des formulaires sort du cadre de cet article, donc pour le moment nous allons simplement ajouter quelques indications au CSS pour lui donner un air convenable.</p> + +<p>Tout d'abord, ajoutons un élément {{htmlelement("style")}} à notre page, dans l'en‑tête HTML. Comme ceci :</p> + +<pre class="brush: html notranslate"><style> + +</style></pre> + +<p>Entre les balises style, ajoutons le CSS suivant, juste comme indiqué :</p> + +<pre class="brush:css; notranslate">form { + /* Uniquement centrer le formulaire sur la page */ + margin: 0 auto; + width: 400px; + /* Encadré pour voir les limites du formulaire */ + padding: 1em; + border: 1px solid #CCC; + border-radius: 1em; +} + +form div + div { + margin-top: 1em; +} + +label { + /* Pour être sûrs que toutes les étiquettes ont même taille et sont correctement alignées */ + display: inline-block; + width: 90px; + text-align: right; +} + +input, textarea { + /* Pour s'assurer que tous les champs texte ont la même police. + Par défaut, les textarea ont une police monospace */ + font: 1em sans-serif; + + /* Pour que tous les champs texte aient la même dimension */ + width: 300px; + box-sizing: border-box; + + /* Pour harmoniser le look & feel des bordures des champs texte */ + border: 1px solid #999; +} + +input:focus, textarea:focus { + /* Pour souligner légèrement les éléments actifs */ + border-color: #000; +} + +textarea { + /* Pour aligner les champs texte multi‑ligne avec leur étiquette */ + vertical-align: top; + + /* Pour donner assez de place pour écrire du texte */ + height: 5em; +} + +.button { + /* Pour placer le bouton à la même position que les champs texte */ + padding-left: 90px; /* même taille que les étiquettes */ +} + +button { + /* Cette marge supplémentaire représente grosso modo le même espace que celui + entre les étiquettes et les champs texte */ + margin-left: .5em; +}</pre> + +<p>Désormais notre formulaire a une bien meilleure allure.</p> + +<p><img alt="" src="/files/4051/form-style.png" style="height: 260px; width: 900px;"></p> + +<div class="note"> +<p><strong>Note</strong> : Il est sur GitHub dans <a href="https://github.com/mdn/learning-area/blob/master/html/forms/your-first-HTML-form/first-form-styled.html">first-form-styled.html</a> (à voir aussi <a href="https://mdn.github.io/learning-area/html/forms/your-first-HTML-form/first-form-styled.html">directement</a>).</p> +</div> + +<h2 id="Envoyer_les_données_au_serveur_Web">Envoyer les données au serveur Web</h2> + +<p>Finalement, gérer les données du formulaire côté serveur web est peut être le plus compliqué. Comme dit auparavant, un formulaire HTML est une manière pratique de demander de l'information à un utilisateur et de les adresser à un serveur web.</p> + +<p>L'élément {{HTMLElement("form")}} définit où et comment les données sont envoyées, merci aux attributs <code>action</code> et <code>method</code>.</p> + +<p>Mais ce n'est pas tout. Nous avons aussi besoin de donner un nom à nos données. Ces noms sont importants pour deux raisons. Du côté du navigateur, cela sert à définir le nom de chaque élément de donnée. Du côté du serveur, chaque information doit avoir un nom pour être manipulée correctement.</p> + +<p>Pour nommer vos données vous devez utiliser l'attribut <code>name</code> pour identifier bien précisément l'élément d'information collecté par chacun des widgets. Regardons à nouveau le code de notre formulaire :</p> + +<pre class="brush:html; notranslate">form action="/my-handling-form-page" method="post"> + <div> + <label for="name">Nom :</label> + <input type="text" id="name" name="user_name" /> + <div> + <div> + <label for="mail">E-mail :</label> + <input type="email" id="mail" name="user_email" /> + </div> + <div> + <label for="msg">Message:</label> + <textarea id="msg" name="user_message"></textarea> + </div> + + ...</pre> + +<p>Dans notre exemple, le formulaire enverra trois informations nommées respectivement « <code>user_name</code> », « <code>user_email </code>» et « <code>user_message</code> ». Ces informations seront envoyées à l'URL « <code>/my-handling-form-page</code> » avec la méthode HTTP POST.</p> + +<p>Du côté du serveur, le script à l'URL « <code>/my-handling-form-page</code><em> </em>» recevra les données sous forme d'une liste de trois éléments clé/valeur intégrés à la requête HTTP. À vous de définir comment ce script va manipuler les données. Chacun des langages serveurs (PHP, Python, Ruby, Java, C#, etc.) a son propre mécanisme pour traiter ces données. Il n'appartient pas à ce guide d'approfondir ce sujet, mais si vous souhaitez en savoir plus, nous avons mis quelques exemples dans l'article <a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_donn%C3%A9es_des_formulaires">Envoi des données de formulaire</a>.</p> + +<h2 id="Résumé">Résumé</h2> + +<p>Félicitations ! Vous avez construit votre premier formulaire HTML. Il ressemble à ceci :</p> + +<p>{{EmbedLiveSample("Un_formulaire_simple", "100%", "240", "", "Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML/Exemple")}}</p> + +<p>Toutefois, ce n'est qu'un début — il est désormais temps de regarder plus en détail. Les formulaires HTML sont bien plus puissants que ce que vous avez pu voir ici et les autres articles de ce guide vous aiderons à maîtriser le reste.</p> + +<p>{{NextMenu("Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML", "Web/Guide/HTML/Formulaires")}}</p> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li>Mon premier formulaire HTML</li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML">Comment structurer un formulaire HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">Les widgets natifs pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets personnalisés pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">Mise en forme des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">Mise en forme avancée des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Table de compatibilité des propriétés pour les widgets de formulaire</a></li> +</ul> diff --git a/files/fr/web/guide/html/formulaires/property_compatibility_table_for_form_widgets/index.html b/files/fr/web/guide/html/formulaires/property_compatibility_table_for_form_widgets/index.html new file mode 100644 index 0000000000..eacb5640ef --- /dev/null +++ b/files/fr/web/guide/html/formulaires/property_compatibility_table_for_form_widgets/index.html @@ -0,0 +1,1991 @@ +--- +title: Table de compatibilité des propriétés pour les widgets de formulaire +slug: Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets +tags: + - Avancé + - CSS + - Formulaires + - Guide + - HTML + - Indésirables + - Mises à jour + - Web +translation_of: Learn/Forms/Property_compatibility_table_for_form_controls +--- +<div>{{learnsidebar}}{{PreviousMenu("Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms", "Web/Guide/HTML/Formulaires")}}</div> + +<p class="summary">Les tables de compatibilité suivantes tentent de résumer l'état de la prise en charge des CSS par les formulaires HTML. Eu égard à la complexité des CSS et des formulaires HTML, ces tables ne peuvent pas être considérées comme un élément de référence parfait. Toutefois, elles vous donneront un bon aperçu de ce qui peut et de ce qui ne peut pas être fait, ce qui vous aidera à apprendre comment faire les choses.</p> + +<h2 id="Comment_lire_les_tables">Comment lire les tables</h2> + +<h3 id="Valeurs">Valeurs</h3> + +<p>Pour chaque propriété, il y a quatre valeurs possibles :</p> + +<dl> + <dt>OUI</dt> + <dd>La prise en charge de la propriété est raisonnablement cohérente d'un navigateur à l'autre. Il se peut que vous soyez encore confronté à des effets collatéraux étranges dans certains cas limites.</dd> + <dt>PARTIEL</dt> + <dd>Bien que la propriété soit acceptée, vous pouvez fréquemment être confronté à des effets collatéraux bizarres ou à des incohérences. Vous devriez probablement éviter ces propriétés si vous n'avez pas d'abord maîtrisé ces effets secondaires.</dd> + <dt>NON</dt> + <dd>La propriété ne fonctionne tout simplement pas ou est si incohérente qu'elle n'est pas fiable.</dd> + <dt>N.A.</dt> + <dd>La propriété n'a aucune signification pour ce type de widget.</dd> +</dl> + +<h3 id="Rendu">Rendu</h3> + +<p>Pour chaque propriété il y a deux rendus possibles :</p> + +<dl> + <dt>N (Normal)</dt> + <dd>Indique que la propriété est appliquée telle quelle.</dd> + <dt>A (Altéré)</dt> + <dd>Indique que la propriété est appliquée avec la règle supplémentaire ci-dessous :</dd> +</dl> + +<pre class="brush: css">* { +/* Ceci désactive l'aspect et le comportement natif des navigateurs basés sur WebKit. */ + -webkit-appearance: none; + +/* Ceci désactive l'aspect et le comportement natif des navigateurs basés sur Gecko. */ + -moz-appearance: none; + +/* Ceci désactive l'aspect et le comportement natif sur plusieurs divers navigateurs + y compris Opera, Internet Explorer et Firefox */ + background: none; +}</pre> + +<h2 id="Tables_de_compatibilité">Tables de compatibilité</h2> + +<h3 id="Comportements_globaux">Comportements globaux</h3> + +<p>Certains comportements sont communs à de nombreux navigateurs au niveau global :</p> + +<dl> + <dt>{{cssxref("border")}}, {{cssxref("background")}}, {{cssxref("border-radius")}}, {{cssxref("height")}}</dt> + <dd>L'utilisation de l'une de ces propriétés peut désactiver partiellement ou totalement l'aspect natif des widgets sur certains navigateurs. Prudence lorsque vous les utilisez.</dd> + <dt>{{cssxref("line-height")}}</dt> + <dd>Cette propriété est prise en charge de manière non cohérente d'un navigateur à l'autre et vous devriez l'éviter.</dd> + <dt>{{cssxref("text-decoration")}}</dt> + <dd>Cette propriété n'est pas prise en charge par Opera sur les widgets de formulaire.</dd> + <dt>{{cssxref("text-overflow")}}</dt> + <dd>Opera, Safari et IE9 ne prennent pas en charge cette propriété sur les widgets de formulaire.</dd> + <dt>{{cssxref("text-shadow")}}</dt> + <dd>Opera ne prend pas en charge {{cssxref("text-shadow")}} sur les widgets de formulaire et IE9 ne le prend pas du tout en charge.</dd> +</dl> + +<h3 id="Champs_texte">Champs texte</h3> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> + <ol> + <li>Les navigateurs WebKit (principalement sur Mac OSX et iOS) utilisent apparence et comportement natifs pour les champs de recherche. Par conséquent, il est nécessaire d'utiliser <code>-webkit-appearance:none</code> pour pouvoir appliquer cette propriété aux champs de recherche.</li> + <li>Sous Windows 7, Internet Explorer 9 n'applique pas la bordure à moins que <code>background:none</code> ne soit utilisé.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> + <ol> + <li>Les navigateurs WebKit (principalement sur Mac OSX et iOS) utilisent apparence et comportement natifs pour les champs de recherche. Par conséquent, il est nécessaire d'utiliser <code>-webkit-appearance:none</code> pour pouvoir appliquer cette propriété aux champs de recherche.</li> + <li>Sous Windows 7, Internet Explorer 9 n'applique pas la bordure à moins que <code>background:none</code> ne soit utilisé.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> + <ol> + <li>Les navigateurs WebKit (principalement sur Mac OSX et iOS) utilisent apparence et comportement natifs pour les champs de recherche. Par conséquent, il est nécessaire d'utiliser <code>-webkit-appearance:none</code> pour pouvoir appliquer cette propriété aux champs de recherche.</li> + <li>Sous Windows 7, Internet Explorer 9 n'applique pas la bordure à moins que <code>background:none</code> ne soit utilisé.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}<sup>[1]</sup></th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> + <ol> + <li>Si la propriété {{cssxref("border-color")}} n'est pas mentionnée, certains navigateurs fondés sur WebKit appliqueront la propriété {{cssxref("color")}} aussi bien à la bordure qu'à la police avec l'élément {{HTMLElement("textarea")}}.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td>Voir la note à propos de {{cssxref("line-height")}}</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td>Voir la note à propos de Opera</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 prend en charge cette propriété uniquement sur les éléments {{HTMLElement("textarea")}}, alors que Opera ne la prend en charge que sur les champs texte sur une ligne.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> + <ol> + <li>Les navigateurs WebKit (principalement sur Mac OSX et iOS) utilisent apparence et comportement natifs pour les champs de recherche. Par conséquent, il est nécessaire d'utiliser<code> -webkit-appearance:none</code> pour pouvoir appliquer cette propriété aux champs de recherche. Sous Windows 7, Internet Explorer 9 n'applique pas la bordure à moins que <code>background:none</code> ne soit utilisé.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> + <ol> + <li>Les navigateurs WebKit (principalement sur Mac OSX et iOS) utilisent apparence et comportement natifs pour les champs de recherche. Par conséquent, il est nécessaire d'utiliser<code> -webkit-appearance:none</code> pour pouvoir appliquer cette propriété aux champs de recherche. Sous Windows 7, Internet Explorer 9 n'applique pas la bordure à moins que <code>background:none</code> ne soit utilisé.</li> + <li>Sur Opera la propriété {{cssxref("border-radius")}} n'est appliquée que si une bordure est explicitement définie.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 ne prend pas en charge cette propriété.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Boutons">Boutons</h3> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> + <ol> + <li>Cette propriété n'est pas appliquée sur les navigateurs fondés sur WebKit sur Mac OSX ou iOS.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> + <ol> + <li>Cette propriété n'est pas appliquée sur les navigateurs fondés sur WebKit sur Mac OSX ou iOS.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td>Voir la note à propos de {{cssxref("line-height")}}.</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td> + <ol> + <li>Sur Opera la propriété {{cssxref("border-radius")}} n'est appliquée que si une bordure est explicitement définie.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 ne prend pas en charge cette propriété.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Widget_number">Widget <code>number</code></h3> + +<p>Sur les navigateurs qui implémentent le widget <code>number</code>, il n'y a pas de méthode standard pour changer le style des roulettes utilisées pour changer la valeur du champ. Il est à noter que les roulettes de Safari sont en dehors du champ.</p> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>Sur Opera, les roulettes sont zoomés, ce qui peut masquer le contenu du champ.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>Sur Opera, les roulettes sont zoomés, ce qui peut masquer le contenu du champ.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td>Voir la note à propos de {{cssxref("line-height")}}.</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière‑plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td colspan="1" rowspan="3"> + <p>Pris en charge mais il y a trop d'incohérence entre les navigateurs pour que ce soit fiable.</p> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + </tr> + </tbody> +</table> + +<h3 id="Cases_à_cocher_et_boutons_radio">Cases à cocher et boutons radio</h3> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non<sup>[1]</sup></td> + <td> + <ol> + <li>Certains navigateurs ajoutent des marges supplémentaires et d'autres étirent le widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non<sup>[1]</sup></td> + <td> + <ol> + <li>Certains navigateurs ajoutent des marges supplémentaires et d'autres étirent le widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Boîtes_à_sélection_(ligne_unique)">Boîtes à sélection (ligne unique)</h3> + +<p>Firefox ne fournit aucun moyen de changer la flèche vers le bas sur l'élément {{HTMLElement("select")}}.</p> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>Cette propriété est correcte sur l'élément {{HTMLElement("select")}}, mais cela peut ne pas être le cas sur les éléments {{HTMLElement("option")}} ou {{HTMLElement("optgroup")}}.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[2]</sup></td> + <td> + <ol> + <li>La propriété est appliquée, mais de manière incohérente entre navigateurs sous Mac OSX.</li> + <li>La propriété est bien appliquée sur l'élément {{HTMLElement("select")}}, mais est traitée de manière incohérente sur les éléments {{HTMLElement("option")}} et {{HTMLElement("optgroup")}}.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>Sur Mac OSX, les navigateurs fondés sur WebKit ne prennent pas en charge cette propriété sur les widgets natifs et, avec Opera, ils ne la prennent pas du tout en charge sur les éléments {{HTMLElement("option")}} et {{HTMLElement("optgroup")}}.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>Sur Mac OSX, les navigateurs fondés sur WebKit ne prennent pas en charge cette propriété sur les widgets natifs et, avec Opera, ils ne la prennent pas du tout en charge sur les éléments {{HTMLElement("option")}} et {{HTMLElement("optgroup")}}.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 ne prend pas en charge cette propriété sur les éléments {{HTMLElement("select")}}, {{HTMLElement("option")}}, et {{HTMLElement("optgroup")}} ; les navigateurs fondés sur WebKit sur Mac OSX ne prennent pas en charge cette propriété sur les éléments {{HTMLElement("option")}} et {{HTMLElement("optgroup")}}.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 sous Windows 7 et les navigateurs fondés sur WebKit sous Mac OSX ne prennent pas en charge cette propriété pour ce widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>Seul Firefox fournit une prise en charge totale de cette propriété. Opera ne la prend pas du tout en charge et d'autres navigateur ne le font que pour l'élément {{HTMLElement("select")}}.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1][2]</sup></td> + <td> + <ol> + <li>La plupart des navigateurs ne prennent en charge cette propriété que pour l'élément {{HTMLElement("select")}}.</li> + <li>IE9 ne prend pas en charge cette propriété.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1][2]</sup></td> + <td> + <ol> + <li>La plupart des navigateurs ne prennent en charge cette propriété que pour l'élément {{HTMLElement("select")}}.</li> + <li>IE9 ne prend pas en charge cette propriété.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>La plupart des navigateurs ne prennent en charge cette propriété que pour l'élément {{HTMLElement("select")}}.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>La plupart des navigateurs ne prennent en charge cette propriété que pour l'élément {{HTMLElement("select")}}.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Boîtes_à_sélection_(multilignes)">Boîtes à sélection (multilignes)</h3> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>Opera ne prend pas en charge {{cssxref("padding-top")}} et {{cssxref("padding-bottom")}} sur l'élément {{HTMLElement("select")}}.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td>Voir la note à propos de {{cssxref("line-height")}}.</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 ne prend pas en charge cette propriété sur les éléments {{HTMLElement("select")}}, {{HTMLElement("option")}}, et {{HTMLElement("optgroup")}} ; les navigateurs fondés sur WebKit sur Mac OSX ne prennent pas en charge cette propriété sur les éléments {{HTMLElement("option")}} et {{HTMLElement("optgroup")}}.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 sous Windows 7 et les navigateurs fondés sur WebKit sous Mac OSX ne prennent pas en charge cette propriété sur ce widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Uniquement pris en charge par Firefox et IE9+.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>La plupart des navigateurs ne prennent en charge cette propriété que pour l'élément {{HTMLElement("select")}}.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td> + <ol> + <li>Sur Opera la propriété {{cssxref("border-radius")}} n'est appliquée que si une bordure est explicitement définie.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 ne prend pas en charge cette propriété.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Datalist">Datalist</h3> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Sélecteur_de_fichiers">Sélecteur de fichiers</h3> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Pris en charge mais il y a trop d'incohérence entre les navigateurs pour que ce soit fiable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>Beaucoup de navigateurs appliquent cette propriété sur le bouton de sélection.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>Agit plus ou moins comme une marge supplementaire en dehors du widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Pris en charge mais il y a trop d'incohérence entre les navigateurs pour que ce soit fiable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 ne prend pas en charge cette propriété.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Sélecteurs_de_date">Sélecteurs de date</h3> + +<p>Beaucoup de propriétés sont prises en charge mais il y a trop d'incohérence entre les navigateurs pour que ce soit fiable.</p> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Sélecteurs_de_couleurs">Sélecteurs de couleurs</h3> + +<p>Il n'y a pas actuellement suffisamment d'implémentation pour obtenir des comportements fiables.</p> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> + <ol> + <li>Opera gère cette propriété comme pour un widget <code>select </code>avec les mêmes restrictions.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> + <ol> + <li>Opera gère cette propriété comme pour un widget <code>select </code>avec les mêmes restrictions.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>Pris en charge mais il y a trop d'incohérence entre les navigateurs pour que ce soit fiable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Widgets_meter_et_progress">Widgets <code>meter</code> et <code>progress</code></h3> + +<p>Il n'y a pas actuellement suffisemment d'implémentation pour obtenir des comportements fiables.</p> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>Chrome cache les éléments {{HTMLElement("progress")}} et {{HTMLElement("meter")}} quand la propriété {{cssxref("padding")}} est appliquée sur un élément altéré.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>Pris en charge mais il y a trop d'incohérence entre les navigateurs pour que ce soit fiable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Widget_range">Widget <code>range</code></h3> + +<p>Il n'y a pas de méthode standard pour changer le style de la poignée de<code> range</code> et Opera n'a aucun moyen de modifier le rendu par défaut du widget <code>range</code>.</p> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td> + <ol> + <li>Chrome et Opera ajoutent quelque espace supplémentaire autour du widget, alors que Opera sous Windows 7 réduit la poignée de <code>range</code>.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">Non</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> + <ol> + <li>La propriété {{cssxref("padding")}} est appliquée, mais elle n'a aucun effet visible.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>Pris en charge mais il y a trop d'incohérence entre les navigateurs pour que ce soit fiable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Boutons_image">Boutons image</h3> + +<table> + <thead> + <tr> + <th scope="col">Propriété</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">A</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Modèle de boîte CSS</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Texte et polices</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td> </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Bordure et arrière-plan</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Oui</td> + <td colspan="1"> </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td colspan="1"> + <ol> + <li>IE9 ne prend pas en charge cette propriété.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partiel<sup>[1]</sup></td> + <td colspan="1"> + <ol> + <li>IE9 ne prend pas en charge cette propriété.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<p>{{PreviousMenu("Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms", "Web/Guide/HTML/Formulaires")}}</p> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML">Mon premier formulaire HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML"><span>Comment structurer un formulaire HTML</span></a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">Les widgets natifs pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets personnalisés pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">Mise en forme des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">Mise en forme avancée des formulaires HTML</a></li> + <li>Table de compatibilité des propriétés pour les widgets de formulaire</li> +</ul> diff --git a/files/fr/web/guide/html/formulaires/sending_forms_through_javascript/index.html b/files/fr/web/guide/html/formulaires/sending_forms_through_javascript/index.html new file mode 100644 index 0000000000..922bfb2aaf --- /dev/null +++ b/files/fr/web/guide/html/formulaires/sending_forms_through_javascript/index.html @@ -0,0 +1,440 @@ +--- +title: Envoi de formulaires avec JavaScript +slug: Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript +translation_of: Learn/Forms/Sending_forms_through_JavaScript +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés", "Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers", "Web/Guide/HTML/Formulaires")}}</div> + +<p class="summary">Comme dans le <a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">précédent article</a>, les formulaires HTML peuvent envoyer une requête HTTP par déclaration. Mais des formulaires peuvent aussi préparer une requête HTTP à adresser via JavaScript. Cet article explore comment faire cela.</p> + +<h2 id="Un_formulaire_n'est_pas_toujours_un_<form>">Un formulaire n'est pas toujours un <form></h2> + +<p>Avec les <a href="/fr/docs/Open_Web_apps_and_Web_standards">applications Web ouvertes</a>, il est de plus en plus courant d'utiliser des <a href="fr/docs/HTML/Forms">formulaires HTML</a> autres que des formulaires à remplir par des personnes — de plus en plus de développeurs prennent le contrôle sur la transmission des données.</p> + +<h3 id="Obtenir_le_contrôle_sur_la_totalité_de_l'interface">Obtenir le contrôle sur la totalité de l'interface</h3> + +<p>La soumission d'un formulaire HTML standard charge l'URL où les données sont envoyées, car la fenêtre du navigateur manipule une pleine page. Éviter de charger une pleine page peut amener plus de fluidité en masquant des clignotements et des lenteurs de réseau.</p> + +<p>De nombreuses UI modernes n'utilisent les formulaires HTML que pour recueillir des données utilisateur. Lorsque l'utilisateur veut envoyer les données, l'application prend la main et transmet les données de manière asynchrone en arrière-plan, mettant à jour uniquement les parties de l'interface utilisateur nécessitant des modifications.</p> + +<p>L'envoi asynchrone de données arbitraires est connu sous le nom AJAX, qui signifie "Asynchronous JavaScript And XML" (XML et JavaScript asynchrones).</p> + +<h3 id="Comment_est-ce_différent">Comment est-ce différent ?</h3> + +<p><a href="/en-US/docs/AJAX">AJAX</a> utilise l'objet DOM {{domxref("XMLHttpRequest")}} (XHR).Il peut construire des requêtes HTTP, les envoyer et retrouver leur résultats.</p> + +<div class="note"> +<p><strong>Note :</strong> Les techniques AJAX anciennes ne se fondaient pas forcément sur {{domxref("XMLHttpRequest")}}. Par exemple, <a href="http://en.wikipedia.org/wiki/JSONP" rel="external">JSONP</a> combiné à la fonction <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/eval"><code>eval()</code></a>. Cela fonctionne, mais n'est pas recommandé en raison de sérieux problèmes de sécurité. La seule raison d'en poursuivre l'utilisation est l'utilisation de navigateurs anciens qui ne prennent pas en charge {{domxref("XMLHttpRequest")}} ou <a href="/fr/docs/Glossaire/JSON">JSON</a>, mais ce sont vraiment des navigateurs anciens ! <strong>Évitez ces techniques.</strong></p> +</div> + +<p> </p> + +<p>Historiquement, {{domxref("XMLHttpRequest")}} a été conçu pour récupérer et envoyer du XML comme format d'échange. Cependant,<a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/JSON"> JSON</a> a remplacé XML et est de plus en plus courant aujourd'hui.</p> + +<p>Mais ni XML ni JSON ne s'adaptent à l'encodage des demandes de données de formulaire. Les données de formulaire (<code>application/x-www-form-urlencoded</code>) sont constituées de listes de paires clé/valeur codées par URL. Pour la transmission de données binaires, la requête HTTP est transformée en données <code>multipart/form‑data</code>.</p> + +<p>Si vous contrôlez le frontal (le code exécuté dans le navigateur) et l'arrière‑plan (le code exécuté sur le serveur), vous pouvez envoyer JSON/XML et les traiter comme vous le souhaitez.</p> + +<p>Mais si vous voulez utiliser un service tiers, ce n'est pas si facile. Certains services n'acceptent que les données de formulaire. Il y a aussi des cas où il est plus simple d'utiliser les données du formulaire. Si les données sont des paires clé/valeur ou des données binaires brutes, des outils d'arrière‑plan existants peuvent les traiter sans code supplémentaire.</p> + +<p>Comment envoyer de telles données ?</p> + +<h2 id="Envoi_des_données_de_formulaire">Envoi des données de formulaire</h2> + +<p>Il y a 3 façons d'envoyer des données de formulaire, allant des techniques existantes jusqu'à l'objet {{domxref("XMLHttpRequest/FormData", "FormData")}} plus récent. Examinons-les en détail.</p> + +<h3 id="Construire_manuellement_un_XMLHttpRequest">Construire manuellement un XMLHttpRequest</h3> + +<p>{{domxref("XMLHttpRequest")}} est la manière la plus sûre et la plus fiable de faire des requêtes HTTP. Pour envoyer des données de formulaire avec {{domxref("XMLHttpRequest")}}, préparez les données par encodage URL et suivez les spécificités des requêtes de données de formulaire.</p> + +<div class="note"> +<p><strong>Note :</strong> Pour en savoir plus sur <code>XMLHttpRequest</code>, ces articles pourraient vous intéresser : un article d'introduction à <a href="/fr/docs/Web/Guide/AJAX/Premiers_pas">AJAX</a> et un didacticiel plus fouillé à ce propos utilisant <a href="/fr/docs/HTML_in_XMLHttpRequest"><code>XMLHttpRequest</code></a>.</p> +</div> + +<p>Reconstruisons l'exemple précédent :</p> + +<pre class="brush: html"><button type="button" onclick="sendData({test:'ok'})">Cliquez ici !</button></pre> + +<p>Comme vous pouvez le voir, le HTML n'a pas réellement changé. Mais, le JavaScript est totalement différent :</p> + +<pre class="brush: js">function sendData(data) { + var XHR = new XMLHttpRequest(); + var urlEncodedData = ""; + var urlEncodedDataPairs = []; + var name; + + // Transformez l'objet data en un tableau de paires clé/valeur codées URL. + for(name in data) { + urlEncodedDataPairs.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name])); + } + + // Combinez les paires en une seule chaîne de caractères et remplacez tous + // les espaces codés en % par le caractère'+' ; cela correspond au comportement + // des soumissions de formulaires de navigateur. + urlEncodedData = urlEncodedDataPairs.join('&').replace(/%20/g, '+'); + + // Définissez ce qui se passe en cas de succès de soumission de données + XHR.addEventListener('load', function(event) { + alert('Ouais ! Données envoyées et réponse chargée.'); + }); + + // Définissez ce qui arrive en cas d'erreur + XHR.addEventListener('error', function(event) { + alert('Oups! Quelque chose s\'est mal passé.'); + }); + + // Configurez la requête + XHR.open('POST', 'https://example.com/cors.php'); + + // Ajoutez l'en-tête HTTP requise pour requêtes POST de données de formulaire + XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + + // Finalement, envoyez les données. + XHR.send(urlEncodedData); +}</pre> + +<p>Voici le résultat en direct :</p> + +<p>{{EmbedLiveSample("Construire_manuellement_un_XMLHttpRequest", "100%", 50)}}</p> + +<div class="note"> +<p><strong>Note :</strong> Cette utilisation de {{domxref("XMLHttpRequest")}} est assujettie à la politique « même origine » si vous voulez envoyer des données à un site web tiers. Pour les demandes d'origine croisée, vous aurez besoin d'un contrôle d'accès <a href="/fr/docs/HTTP/Access_control_CORS">CORS et HTTP</a>.</p> +</div> + +<h3 id="Utilisation_de_XMLHttpRequest_et_de_l'objet_FormData">Utilisation de XMLHttpRequest et de l'objet FormData</h3> + +<p>Construire manuellement une requête HTTP peut devenir fastidieux. Heureusement, une <a href="http://www.w3.org/TR/XMLHttpRequest/">spécification XMLHttpRequest</a> récente fournit un moyen pratique et plus simple pour traiter les demandes de données de formulaire avec l'objet {{domxref("XMLHttpRequest/FormData", "FormData")}}.</p> + +<p>L'objet {{domxref("XMLHttpRequest/FormData", "FormData")}} peut s'utiliser pour construire des données de formulaire pour la transmission ou pour obtenir les données des élément de formulaire de façon à gérer leur mode d'envoi. Notez que les objets {{domxref("XMLHttpRequest/FormData", "FormData")}} sont en écriture seule (« write only »), ce qui signifie que vous pouvez les modifier, mais pas récupérer leur contenu.</p> + +<p>L'utilisation de cet objet est détaillée dans <a href="/fr/docs/Web/API/FormData/Utilisation_objets_FormData">Utiliser les objets FormData</a>, mais voici deux exemples :</p> + +<h4 id="Utiliser_un_objet_FormData_autonome">Utiliser un objet FormData autonome</h4> + +<pre class="brush: html"><button type="button" onclick="sendData({test:'ok'})">Cliquez ici !</button></pre> + +<p>Vous devriez être familier de cet exemple HTML.</p> + +<pre class="brush: js">function sendData(data) { + var XHR = new XMLHttpRequest(); + var FD = new FormData(); + + // Mettez les données dans l'objet FormData + for(name in data) { + FD.append(name, data[name]); + } + + // Définissez ce qui se passe si la soumission s'est opérée avec succès + XHR.addEventListener('load', function(event) { + alert('Ouais ! Données envoyées et réponse chargée.'); + }); + + // Definissez ce qui se passe en cas d'erreur + XHR.addEventListener('error', function(event) { + alert('Oups! Quelque chose s\'est mal passé.'); + }); + + // Configurez la requête + XHR.open('POST', 'https://example.com/cors.php'); + + // Expédiez l'objet FormData ; les en-têtes HTTP sont automatiquement définies + XHR.send(FD); +}</pre> + +<p>Voici le résultat directement :</p> + +<p>{{EmbedLiveSample("Utiliser_un_objet_FormData_autonome", "100%", 60)}}</p> + +<h4 id="Utiliser_un_objet_FormData_lié_à_un_élément_form">Utiliser un objet FormData lié à un élément form</h4> + +<p>Vous pouvez également lier un objet <code>FormData</code> à un élément {{HTMLElement("form")}} et créer ainsi un <code>FormData</code> représentant les données contenues dans le formulaire.</p> + +<p>Le HTML est classique :</p> + +<pre class="brush: html"><form id="myForm"> + <label for="myName">Dites-moi votre nom :</label> + <input id="myName" name="name" value="John"> + <input type="submit" value="Envoyer !"> +</form></pre> + +<p>Mais JavaScript sera de la forme :</p> + +<pre class="brush: js">window.addEventListener("load", function () { + function sendData() { + var XHR = new XMLHttpRequest(); + + // Liez l'objet FormData et l'élément form + var FD = new FormData(form); + + // Définissez ce qui se passe si la soumission s'est opérée avec succès + XHR.addEventListener("load", function(event) { + alert(event.target.responseText); + }); + + // Definissez ce qui se passe en cas d'erreur + XHR.addEventListener("error", function(event) { + alert('Oups! Quelque chose s\'est mal passé.'); + }); + + // Configurez la requête + XHR.open("POST", "https://example.com/cors.php"); + + // Les données envoyées sont ce que l'utilisateur a mis dans le formulaire + XHR.send(FD); + } + + // Accédez à l'élément form … + var form = document.getElementById("myForm"); + + // … et prenez en charge l'événement submit. + form.addEventListener("submit", function (event) { + event.preventDefault(); + + sendData(); + }); +});</pre> + +<p>Voici le résultat en direct :</p> + +<p>{{EmbedLiveSample("Utiliser_un_objet_FormData_lié_à_un_élément_form", "100%", 70)}}</p> + +<p>Vous pouvez même intervenir davantage dans le processus en utilisant la propriété {{domxref("HTMLFormElement.elements", "elements")}} du formulaire pour obtenir une liste de tous les éléments de données du formulaire et les gérer chacun individuellement dans le programme. Pour en savoir plus, voir l'exemple dans la {{SectionOnPage("/en-US/docs/Web/API/HTMLFormElement.elements", "Accessing the element list's contents")}}.</p> + +<h3 id="Construire_un_DOM_dans_un_iframe_caché">Construire un DOM dans un <code>iframe</code> caché</h3> + +<p>La plus ancienne façon d'expédier des données de formulaire de manière asynchrone consiste à construire un formulaire avec l'API DOM, puis d'envoyer ses données dans un {{HTMLElement("iframe")}} caché. Pour accéder au résultat de votre envoi, il suffit de récupérer le contenu de l'élément {{HTMLElement("iframe")}}.</p> + +<div class="warning"> +<p><strong>Avertissement :</strong> <strong>Évitez d'employer cette technique.</strong> Il y a des risques concernant la sécurité avec des services tierce-partie car vous laissez ouverte la possibilité d'une <a href="https://fr.wikipedia.org/wiki/Cross-site_scripting" rel="external">attaque par injection de script</a>. Si vous utilisez HTTPS, il reste possible de perturber la <a href="/fr/docs/JavaScript/Same_origin_policy_for_JavaScript">politique de la même origine</a>, ce qui peut rendre le contenu de l'élément {{HTMLElement("iframe")}} inatteignable. Toutefois, cette méthode peut être votre seule possibilité si vous devez prendre en charge des navigateurs très anciens.</p> +</div> + +<p>Voici un exemple :</p> + +<pre class="brush: html"><button onclick="sendData({test:'ok'})">Cliquez ici !</button></pre> + +<pre class="brush: js">// Créer l'iFrame servant à envoyer les données +var iframe = document.createElement("iframe"); +iframe.name = "myTarget"; + +// Puis, attachez l'iFrame au document principal +window.addEventListener("load", function () { + iframe.style.display = "none"; + document.body.appendChild(iframe); +}); + +// Voici la fonction réellement utilisée pour expédier les données +// Elle prend un paramètre, qui est un objet chargé des paires clé/valeurs. +function sendData(data) { + var name, + form = document.createElement("form"), + node = document.createElement("input"); + + // Définir ce qui se passe quand la réponse est chargée + iframe.addEventListener("load", function () { + alert("Ouais ! Données envoyés."); + }); + + form.action = "http://www.cs.tut.fi/cgi-bin/run/~jkorpela/echo.cgi"; + form.target = iframe.name; + + for(name in data) { + node.name = name; + node.value = data[name].toString(); + form.appendChild(node.cloneNode()); + } + + // Pour être envoyé, le formulaire nécessite d'être attaché au document principal. + form.style.display = "none"; + document.body.appendChild(form); + + form.submit(); + + // Une fois le formulaire envoyé, le supprimer. + document.body.removeChild(form); +}</pre> + +<p>Voici le résultat en direct :</p> + +<p>{{EmbedLiveSample('Construire_un_DOM_dans_un_iframe_caché', "100%", 50)}}</p> + +<p> </p> + +<h2 id="Gestion_des_données_binaires"><span>Gestion des données binaires</span></h2> + +<p>Si vous utilisez un objet {{domxref("XMLHttpRequest/FormData", "FormData")}} avec un formulaire qui inclut des widgets <code><input type="file"></code>, les données seront traitées automatiquement. Mais pour envoyer des données binaires à la main, il y a un travail supplémentaire à faire.</p> + +<p>Il existe de nombreuses sources de données binaires sur le Web moderne : {{domxref("FileReader")}}, {{domxref("HTMLCanvasElement", "Canvas")}} et <a href="/fr/docs/WebRTC/navigator.getUserMedia">WebRTC</a>, par exemple. Malheureusement, certains anciens navigateurs ne peuvent pas accéder aux données binaires ou nécessitent des solutions de contournement compliquées. Ces cas hérités sont hors du champ d'application de cet article. Si vous voulez en savoir plus sur l'API FileReader, lisez <a href="/fr/docs/Using_files_from_web_applications">Utiliser les fichiers des applications Web</a>.</p> + +<p>Envoyer des données binaires avec le support de {{domxref("XMLHttpRequest/FormData", "FormData")}} est direct. Utilisez la méthode append() et vous avez terminé. Si vous devez le faire à la main, c'est plus délicat.</p> + +<p>Dans l'exemple suivant, nous utilisons l'API {{domxref("FileReader")}} pour accéder aux données binaires et ensuite nous construisons à la main la demande de données du formulaire en plusieurs parties :</p> + +<pre class="brush: html"><form id="myForm"> + <p> + <label for="i1">Données textuelles :</label> + <input id="i1" name="myText" value="Quelques données textuelles"> + </p> + <p> + <label for="i2">Fichier de données :</label> + <input id="i2" name="myFile" type="file"> + </p> + <button>Envoyer !</button> +</form></pre> + +<p>Comme vous pouvez le voir, le HTML est un <code><form></code>standard. Il n'y a rien de magique là‑dedans. La « magie » est dans le JavaScript :</p> + +<pre class="brush: js">// Comme nous voulons avoir accès à un nœud DOM, +// nous initialisons le script au chargement de la page. +window.addEventListener('load', function () { + + // Ces variables s'utilisent pour stocker les données du formulaire + var text = document.getElementById("i1"); + var file = { + dom : document.getElementById("i2"), + binary : null + }; + + // Nous utilisons l'API de FileReader pour accéder au contenu du fichier + var reader = new FileReader(); + + // Comme FileReader est asynchrone, stockons son résulata + // quand il a fini de lire le fichier + reader.addEventListener("load", function () { + file.binary = reader.result; + }); + + // Au chargement de la page, si un fichier est déjà choisi, lisons‑le + if(file.dom.files[0]) { + reader.readAsBinaryString(file.dom.files[0]); + } + + // Sinon, lisons le fichier une fois que l'utilisateur l'a sélectionné + file.dom.addEventListener("change", function () { + if(reader.readyState === FileReader.LOADING) { + reader.abort(); + } + + reader.readAsBinaryString(file.dom.files[0]); + }); + + // sendData est notre fonction principale + function sendData() { + // S'il y a un fichier sélectionné, attendre sa lecture + // Sinon, retarder l'exécution de la fonction + if(!file.binary && file.dom.files.length > 0) { + setTimeout(sendData, 10); + return; + } + + // Pour construire notre requête de données de formulaire en plusieurs parties + // nous avons besoin d'une instance de XMLHttpRequest + var XHR = new XMLHttpRequest(); + + // Nous avons besoin d'un séparateur pour définir chaque partie de la requête + var boundary = "blob"; + + // Stockons le corps de la requête dans une chaîne littérale + var data = ""; + + // Ainsi, si l'utilisateur a sélectionné un fichier + if (file.dom.files[0]) { + // Lancer une nouvelle partie de la requête du corps + data += "--" + boundary + "\r\n"; + + // Décrivons là comme étant des données du formulaire + data += 'content-disposition: form-data; ' + // Définissons le nom des données du formulaire + + 'name="' + file.dom.name + '"; ' + // Fournissons le vrai nom du fichier + + 'filename="' + file.dom.files[0].name + '"\r\n'; + // et le type MIME du fichier + data += 'Content-Type: ' + file.dom.files[0].type + '\r\n'; + + // Il y a une ligne vide entre les métadonnées et les données + data += '\r\n'; + + // Ajoutons les données binaires à la requête du corps + data += file.binary + '\r\n'; + } + + // C'est plus simple pour les données textuelles + // Démarrons une nouvelle partie dans notre requête du corps + data += "--" + boundary + "\r\n"; + + // Disons que ce sont des données de formulaire et nommons les + data += 'content-disposition: form-data; name="' + text.name + '"\r\n'; + // Il y a une ligne vide entre les métadonnées et les données + data += '\r\n'; + + // Ajoutons les données textuelles à la requête du corps + data += text.value + "\r\n"; + + // Ceci fait, "fermons" la requête du corps + data += "--" + boundary + "--"; + + // Définissons ce qui arrive en cas de succès pour la soumission des données + XHR.addEventListener('load', function(event) { + alert('Ouais ! Données expédiées et réponse chargée.'); + }); + + // Définissons ce qui se passe en cas d'eerreur + XHR.addEventListener('error', function(event) { + alert('Oups! Quelque chose s\'est mal passé.'); + }); + + // Configurons la requête + XHR.open('POST', 'https://example.com/cors.php'); + + // Ajoutons l'en-tête requise pour gèrer la requête POST des données + // de formulaire en plusieurs parties + XHR.setRequestHeader('Content-Type','multipart/form-data; boundary=' + boundary); + + // et finalement, expédions les données. + XHR.send(data); + } + + // Accéder au formulaire … + var form = document.getElementById("myForm"); + + // … pour prendre en charge l'événement soumission + form.addEventListener('submit', function (event) { + event.preventDefault(); + sendData(); + }); +});</pre> + +<p>Voici le résultat en direct :</p> + +<p>{{EmbedLiveSample('Gestion_des_données_binaires', "100%", 150)}}</p> + +<h2 id="Conclusion">Conclusion</h2> + +<p>Selon le navigateur, l'envoi de données de formulaire par JavaScript peut être facile ou difficile. L'objet {{domxref("XMLHttpRequest/FormData", "FormData")}} en est généralement la cause et n'hésitez pas à utiliser un « polyfill » (<a href="https://fr.wikipedia.org/wiki/Polyfill">prothèse d'émulation</a>) pour cela sur les navigateurs anciens :</p> + +<ul> + <li><a href="https://gist.github.com/3120320" rel="external">Ces primitives</a> sont des « polyfills » de <code>FormData</code> avec des {{domxref("Using_web_workers","worker")}}.</li> + <li><a href="https://github.com/francois2metz/html5-formdata" rel="external">HTML5-formdata</a> tente d'opérer un « polyfill » de l'objet <code>FormData</code>, mais il requiert un <a href="http://www.w3.org/TR/FileAPI/" rel="external">File API</a></li> + <li><a href="https://github.com/jimmywarting/FormData">Ce « polyfill »</a> fournit la plupart des nouvelles méthodes dont <code>FormData</code> dispose (entrées, clés, valeurs et prise en charge de <code>for...of</code>)</li> +</ul> + +<p> </p> + +<div>{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés", "Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers", "Web/Guide/HTML/Formulaires")}}</div> + +<p> </p> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML">Mon premier formulaire HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML"><span>Comment structurer un formulaire HTML</span></a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">Les widgets natifs pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets personnalisés pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">Mise en forme des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">Mise en forme avancée des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Table de compatibilité des propriétés pour les widgets de formulaire</a></li> +</ul> diff --git a/files/fr/web/guide/html/formulaires/validation_donnees_formulaire/index.html b/files/fr/web/guide/html/formulaires/validation_donnees_formulaire/index.html new file mode 100644 index 0000000000..ccbac0ef15 --- /dev/null +++ b/files/fr/web/guide/html/formulaires/validation_donnees_formulaire/index.html @@ -0,0 +1,874 @@ +--- +title: Validation des données de formulaires +slug: Web/Guide/HTML/Formulaires/Validation_donnees_formulaire +tags: + - Exemple + - Formulaires + - Guide + - HTML + - Intermédiaire + - JavaScript + - Web +translation_of: Learn/Forms/Form_validation +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires", "Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés", "Web/Guide/HTML/Formulaires")}}</div> + +<p class="summary">Ce n'est pas tout d'envoyer des données — il faut aussi s'assurer que les données mises dans un formulaire par un utilisateur sont dans un format correct pour pouvoir être traitées correctement et qu'elles ne vont pas casser nos applications. Nous voulons également aider les utilisateurs à compléter les formulaires correctement et à ne pas ressentir de frustration en essayant d'utiliser les applications. La validation des données de formulaire vous aide à remplir ces objectifs — cet article indique ce qu'il est nécessaire de savoir.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td>Notions concernant les ordinateurs, une bonne compréhension du <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML">HTML</a>, des <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS">CSS</a> et de <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript">JavaScript</a>.</td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td>Comprendre ce qu'est la validation d'un formulaire, pourquoi c'est important et comment la mettre en œuvre.</td> + </tr> + </tbody> +</table> + +<h2 id="Qu'est‑ce_qu'une_validation_de_formulaire">Qu'est‑ce qu'une validation de formulaire?</h2> + +<p>Allez sur n'importe quel site à la mode avec un formulaire d'inscription et vous remarquerez des retours si vous n'entrez pas les données dans le format attendu. Vous aurez des messages comme :</p> + +<ul> + <li>« Ce champ est obligatoire » (vous ne pouvez pas le laisser vide)</li> + <li>« Veuillez entrer votre numéro de téléphone au format xxx-xxxx » (il attend trois chiffres suivis d'un tiret, suivi de quatre chiffres).</li> + <li>« Veuillez entrer une adresse e-mail valide » (ce que vous avez saisi ne ressemble pas à une adresse e-mail valide).</li> + <li>« Votre mot de passe doit comporter entre 8 et 30 caractères et contenir une majuscule, un symbole et un chiffre » (sérieusement ?).</li> +</ul> + +<p>C'est ce qu'on appelle la validation de formulaire — lorsque vous saisissez des données, l'application Web vérifie si elles sont correctes. Si elles sont correctes, l'application permet que les données soient soumises au serveur et (généralement) sauvegardées dans une base de données ; si ce n'est pas le cas, elle émet des messages d'erreur pour expliquer ce que vous avez fait de mal (pour autant que vous l'ayez fait). La validation des formulaires peut être mise en œuvre de différentes manières.</p> + +<p>La vérité est qu'aucun d'entre nous n'<em>aime</em> remplir des formulaires — les formulaires ennuient les utilisateurs, tout le prouve : cela les incite à partir et à aller voir ailleurs s'ils sont mal faits. Bref, les formulaires, c'est nullissime.</p> + +<p>Remplir des formulaires web doit être aussi facile que possible. Alors pourquoi être tatillons et bloquer les utilisateurs à chaque fois ? Il y a trois raisons principales :</p> + +<ul> + <li><strong>obtenir de bonnes données dans un bon format</strong> — les applications ne tourneront pas correctement si les données utilisateur sont stockées dans un format fantaisiste, ou si les bonnes informations ne sont pas aux bons endroits ou totalement omises.</li> + <li><strong>protéger nos utilisateurs</strong> — s'ils entrent un mot de passe facile à deviner ou aucun, des utilisateurs malveillants peuvent aisément accéder à leurs comptes et voler leurs données.</li> + <li><strong>nous protéger nous‑mêmes</strong> — il existe de nombreuses façons dont les utilisateurs malveillants peuvent utiliser les formulaires non protégés pour endommager l'application dans laquelle ils se trouvent (voir <a href="/fr/docs/Learn/Server-side/First_steps/Website_security">Sécurité du site Web</a>).</li> +</ul> + +<h3 id="Les_divers_types_de_validation_de_formulaire">Les divers types de validation de formulaire</h3> + +<p>Vous rencontrerez différents types de validation de formulaires sur le Web :</p> + +<ul style="list-style-type: disc;"> + <li>La validation côté client est la validation qui est effectuée dans le navigateur, avant que les données n'aient été soumises au serveur. Cette méthode est plus conviviale que la validation côté serveur car elle donne une réponse instantanée. Il est possible de la subdiviser encore avec : + <ul> + <li>la validation JavaScript, codée en JavaScript, entièrement personnalisable.</li> + <li>la validation de formulaire intégrée avec les fonctions de validation de formulaire HTML5. Elle ne nécessite généralement pas de JavaScript, a de meilleures performances, mais elle n'est pas aussi personnalisable.</li> + </ul> + </li> +</ul> + +<dl> +</dl> + +<ul> + <li>La validation côté serveur est la validation opérée sur le serveur, après que les données ont été soumises — le code côté serveur est utilisé pour valider les données avant de les mettre dans la base de données. Si elles sont erronées, une réponse est envoyée au client pour dire à l'utilisateur ce qui a mal tourné. La validation côté serveur n'est pas aussi conviviale que la validation côté client, car elle nécessite un aller-retour vers le serveur, mais c'est la dernière ligne de défense de votre application contre les mauvaises données (c'est-à-dire les données incorrectes, voire malveillantes). Tous les modèles de canevas de vérification courants côté serveur ont des fonctions de validation et de nettoyage des données (ce qui les sécurise).</li> +</ul> + +<p>Dans le monde réel, les développeurs ont tendance à utiliser une combinaison de validations côté client et côté serveur, pour être du côté sûr.</p> + +<h2 id="Utiliser_la_validation_intégrée_au_formulaire">Utiliser la validation intégrée au formulaire</h2> + +<p>Une des caractéristiques de <a href="/fr/docs/HTML/HTML5">HTML5</a> est la possibilité de valider la plupart des données utilisateur sans avoir recours à des scripts. Ceci se fait en utilisant des <a href="/fr/docs/Web/Guide/HTML/HTML5/Constraint_validation">attributs de validation</a> sur les éléments de formulaire ; ils vous permettent de spécifier des règles pour une entrée de formulaire comme : une valeur doit‑elle être remplie ? y a-t-il une longueur minimale et/ou maximale des données ? doit‑elle être un nombre, une adresse e-mail ou autre chose ? doit‑elle correspondre à un modèle ? Si les données saisies suivent toutes ces règles, elles sont considérées comme valides ; si ce n'est pas le cas, elles sont considérées comme non valides.<br> + Quand un élément est valide :</p> + +<ul> + <li>l'élément correspond à la pseudo‑classe CSS {{cssxref(":valid")}} ; cela vous permet d'appliquer une composition de style distinctive.</li> + <li>si l'utilisateur essaie d'envoyer les données, le navigateur soumet le formulaire pour autant qu'il n'y ait rien d'autre qui l'empêche de le faire (par ex. du JavaScript).</li> +</ul> + +<p>Quand un élément est invalide :</p> + +<ul> + <li>l'élément correspond à la pseudo‑classe CSS {{cssxref(":invalid")}} ; cela vous permet d'appliquer une composition de style distinctive.</li> + <li>si l'utilisateur essaie d'envoyer le formulaire, le navigateur le bloquera et affichera un message d'erreur.</li> +</ul> + +<h3 id="Contraintes_de_validation_sur_les_éléments_d'entrée_—_simple_début">Contraintes de validation sur les éléments d'entrée — simple début</h3> + + + +<p>Dans cette section, nous examinerons quelques unes des diverses fonctionnalités HTML5 peuvant être utilisées pour valider des éléments d'{{HTMLElement("input")}}.</p> + +<p>Commençons par un exemple simple — une entrée ouvrant un choix, selon votre préférence, entre banane ou cerise. Il faut un texte {{HTMLElement("input")}} simple avec une étiquette correspondante et un {{htmlelement("button")}} de soumission. Le code source est sur GitHub à l'adresse <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a> et un exemple « live » ci-dessous :</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html"><form> + <label for="choose">Préférez‑vous la banane ou la cerise ?</label> + <input id="choose" name="i_like"> + <button>Soumettre</button> +</form></pre> + +<pre class="brush: css">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 1px solid black; +}</pre> +</div> + +<p>{{EmbedLiveSample("Hidden_code", "100%", 55)}}</p> + +<p>Pour commencer, faites une copie de fruit-start.html dans un nouveau répertoire sur votre disque dur.</p> + +<h3 id="L'attribut_required">L'attribut required</h3> + +<p>La fonctionnalité de validation HTML5 la plus simple à utiliser est l'attribut {{htmlattrxref("required", "input")}}} — si vous voulez rendre une entrée obligatoire, vous pouvez marquer l'élément en utilisant cet attribut. Lorsque cet attribut est mis, le formulaire ne sera pas soumis (et affichera un message d'erreur) si l'entrée est vide (l'entrée sera également considérée comme invalide).</p> + +<p>Ajoutez un attribut <code>required</code> à votre saisie, comme montré ci‑dessous :</p> + +<pre class="brush: html"><form> + <label for="choose">Préférez-vous la banane ou la cerise ?</label> + <input id="choose" name="i_like" required> + <button>Soumettre</button> +</form></pre> + +<p>Notez aussi le CSS incorporé dans le fichier exemple :</p> + +<pre class="brush: css">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 1px solid black; +}</pre> + +<p>L'entrée a une bordure en pointillés rouge vif lorsqu'elle n'est pas valide, et une bordure noire plus subtile lorsqu'elle est valide. Essayez le nouveau comportement dans l'exemple ci-dessous :</p> + +<p>{{EmbedLiveSample("L'attribut_required", "100%", 55)}}</p> + +<h3 id="Validation_selon_une_expression_régulière">Validation selon une expression régulière</h3> + +<p>Une autre fonctionnalité de validation très courante est l'attribut {{htmlattrxref("pattern", "input")}}, qui attend une <a href="/fr/docs/Web/JavaScript/Guide/Expressions_régulières">expression régulière</a> comme valeur. Une expression régulière (regex) est un modèle qui peut être utilisé pour faire correspondre des combinaisons de caractères dans des chaînes de texte, de sorte qu'elles sont idéales pour la validation de formulaires (ainsi que diverses autres utilisations en JavaScript). Les Regex sont assez complexes et nous n'avons pas l'intention de vous les enseigner de manière exhaustive dans cet article.</p> + +<p>Vous trouverez ci-dessous quelques exemples pour vous donner une idée de base de leur fonctionnement :</p> + +<ul> + <li><code>a</code> — correspond à un caractère qui doit être un a (ni b, ni aa, etc.)</li> + <li><code>abc</code> — correspond à <code>a</code>, suivi de <code>b</code>, suivi de <code>c</code>.</li> + <li><code>a*</code> — correspond au caractère a, absent ou présent plusieurs fois (<code>+</code> correspond à un caractère une ou plusieurs fois).</li> + <li><code>[^a]</code> — correspond à un caractère qui <strong>n'est pas</strong> un a.</li> + <li><code>a|b</code> — correspond à un caractère qui est a ou b.</li> + <li><code>[abc]</code> — correspond à un caractère qui est a, b ou c.</li> + <li><code>[^abc]</code> — correspond à un caractère qui <strong>n'est pas</strong> a, b ou c.</li> + <li><code>[a-z]</code> — correspond à tout caractère de la plage a–z, en minuscules seulement (utilisez <code>[A-Za-z]</code> pour minuscules et majuscules et <code>[A-Z]</code> pour les majuscules uniquement).</li> + <li><code>a.c</code> — correspond à a, suivi par n'importe quel caractère,suivi par c.</li> + <li><code>a{5}</code> — correspond à a, 5 fois.</li> + <li><code>a{5,7}</code> — correspond à a, 5 à 7 fois, mais ni plus, ni moins.</li> +</ul> + +<p>Vous pouvez utiliser des nombres ou d'autres caractères dans ces expressions, comme :</p> + +<ul> + <li><code>[ -]</code> — correspond à une espace ou un tiret.</li> + <li><code>[0-9]</code> — correspond à tout nombre compris entre 0 et 9.</li> +</ul> + +<p>Vous pouvez combiner cela pratiquement comme vous l'entendez en précisant les différentes parties les unes après les autres :</p> + +<ul> + <li><code>[Ll].*k</code> — Un seul caractère L en majuscules ou minuscules, suivi de zéro ou plusieurs caractères de n'importe quel type, suivis par un k minuscules.</li> + <li><code>[A-Z][A-Za-z' -]+</code> — Un seul caractère en majuscules suivi par un ou plusieurs caractères en majuscules ou minuscules, un tiret, une apostrophe ou une espace. Cette combinaison peut s'utiliser pour valider les nom de villes dans les pays anglo‑saxons ; ils débutent par une majuscule et ne contiennent pas d'autre caractère. Quelques exemples de ville de GB correspondant à ce schéma : Manchester, Ashton-under-lyne et Bishop's Stortford.</li> + <li><code>[0-9]{3}[ -][0-9]{3}[ -][0-9]{4}</code> — Un schéma pour un numéro de téléphone intérieur américain — trois chiffres, suivis par une espace ou un tiret, suivis par trois nombres, suivis par une espace ou un tiret, suivis par quatre nombres. Vous aurez peut-être à faire plus compliqué, car certains écrivent leur numéro de zone entre parenthèses, mais ici il s'agit simplement de faire une démonstration.</li> +</ul> + +<p>Voyons un exemple — mettons à jour notre HTML en y ajoutant un attribut <code>pattern</code>, ainsi :</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><form> + <label for="choose">Préférez‑vous la banane ou la cerise ?</label> + <input id="choose" name="i_like" required pattern="banane|cerise"> + <button>Soumettre</button> +</form></code></pre> + +<div class="hidden"> +<pre class="brush: css line-numbers language-css"><code class="language-css">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 1px solid black; +}</code></pre> +</div> + +<p>{{EmbedLiveSample("Validation_selon_une_expression_régulière", "100%", 55)}}</p> + +<p>Dans cet exemple, l'élément {{HTMLElement("input")}}} accepte l'une des deux valeurs possibles : la chaîne « banane » ou la chaîne « cerise ».</p> + +<p>Maintenant, essayez de changer la valeur à l'intérieur de l'attribut <code>pattern</code> suivant certains exemples vus plus haut et regardez comment les valeurs entrées en sont affectées pour rester valides. Écrivez vos propres textes et voyez comment vous vous en sortez ! Restez dans le domaine des fruits dans la mesure du possible, afin que vos exemples aient du sens !</p> + +<div class="note"> +<p><strong>Note :</strong> Certains types d'éléments {{HTMLElement("input")}} n'ont pas besoin d'un attribut {{htmlattrxref("pattern", "input")}} pour être validés. Spécifier le type <code>email</code>, par exemple, valide la valeur saisie par rapport à une expression régulière correspondant à une adresse e‑mail bien formée (ou une liste d'adresses e‑mail séparées par des virgules si elle possède l'attribut {{htmlattrxref("multiple", "input")}}. Comme autre exemple, les champs de type <code>url</code> vont automatiquement nécessiter une URL correctement formée.</p> +</div> + +<div class="note"> +<p><strong>Note : </strong>L'élément {{HTMLElement("textarea")}} ne prend pas en charge l'attribut {{htmlattrxref("pattern", "input")}}.</p> +</div> + +<h3 id="Limitation_de_la_taille_des_entrées">Limitation de la taille des entrées</h3> + +<p>Tous les champs de texte créés avec ({{HTMLElement("input")}} ou {{HTMLElement("textarea")}}) peuvent être limités en taille avec les attributs {{htmlattrxref("minlength", "input")}} et {{htmlattrxref("maxlength", "input")}}. Le champ sera invalide si sa taille est inférieure à la valeur {{htmlattrxref("minlength", "input")}} ou supérieure la valeur {{htmlattrxref("maxlength", "input")}}. Souvent, les navigateurs ne permettent pas aux utilisateurs de saisir des textes de grande longueur dans les champs texte, mais il peut être utile de disposer d'un contrôle plus fin.</p> + +<p>Pour les champs numériques (c'est à dire, <type d'entrée="nombre">), les attributs {{htmlattrxref("min", "input")}} et {{htmlattrxref("max", "input")}} permettent également des contraintes de validité. Si la valeur du champ est inférieure à l'attribut {{htmlattrxref("min", "input")}} ou supérieure à l'attribut {{htmlattrxref("max", "input")}}, le champ ne sera pas valide.</p> + +<p>Prenons un autre exemple. Créez une nouvelle copie du fichier <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a>.</p> + +<p>Supprimez maintenant le contenu de l'élément <code><body></code> et remplacez-le par le suivant :</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><form> + <div> + <label for="choose">Préférez‑vous la banane ou la cerise ?</label> + <input id="choose" name="i_like" required minlength="6" maxlength="6"> + </div> + <div> + <label for="number">Combien en voulez‑vous ?</label> + <input type="number" id="number" name="amount" value="1" min="1" max="10"> + </div> + <div> + <button>Soumettre</button> + </div> +</form></code></pre> + +<ul> + <li>Ici, nous avons donné au champ de texte une taille minimale et maximale de 6 caractères — la même que celle de <em>banane</em> ou <em>cerise</em>. La saisie de moins de 6 caractères s'affichera comme non valide et la saisie de plus de 6 caractères ne sera pas possible dans la plupart des navigateurs.</li> + <li>Nous avons également contraint le champ <code>number</code> à un <code>min</code> de 1 et un <code>max </code>de 10 — les nombres entrés hors de cette plage seront affichés comme non valides, et vous ne pourrez pas utiliser les flèches d'incrémentation/décrémentation pour porter la valeur en dehors de cette plage.</li> +</ul> + +<div class="hidden"> +<pre class="line-numbers language-html"><code class="language-html">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +} + +div { + margin-bottom: 10px; +}</code></pre> +</div> + +<p>Voici cet exemple s'exécutant en « live » :</p> + +<p>{{EmbedLiveSample('Limitation_de_la_taille_des_entrées', "100%", 100)}}</p> + +<div class="note"> +<p><strong>Note</strong>: <code><input type="number"></code> (et d'autres types, comme <code>range</code>) acceptent aussi un attribut {{htmlattrxref("step", "input")}} qui spécifie l'incrément en plus ou en moins de la valeur quand les contrôles d'entrée sont utilisés (comme les boutons <kbd>^</kbd> et <kbd>v</kbd>).</p> +</div> + +<h3 id="Exemple_complet">Exemple complet</h3> + +<p>Voici un exemple complet montrant l'utilisation des fonctionnalités HTML intégrées pour la validation :</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>form</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>fieldset</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>legend</span><span class="punctuation token">>Qualité</span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>abbr</span> <span class="attr-name token">title</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>Ce champ est obligatoire<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>*<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>abbr</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>legend</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>radio<span class="punctuation token">"</span></span> <span class="attr-name token">required</span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>title<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>r1<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>Mr<span class="punctuation token">"</span></span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>r1<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>M.<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>radio<span class="punctuation token">"</span></span> <span class="attr-name token">required</span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>title<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>r2<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>Ms<span class="punctuation token">"</span></span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>r2<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Mme.<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>fieldset</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>n1<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Quel est votre âge ?<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="comment token"><!-- L'attribut pattern peut servir de recours pour les navigateurs dont le type number n'est + pas implémenté pour input mais qui prennent en charge l'attribut pattern. Veuillez noter + que les navigateurs prenant en charge l'attribut pattern ne signalent pas d'erreur quand + il est utilisé avec un champ number. Seule son utilisation ici agit en tant que recours. --></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>number<span class="punctuation token">"</span></span> <span class="attr-name token">min</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>12<span class="punctuation token">"</span></span> <span class="attr-name token">max</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>120<span class="punctuation token">"</span></span> <span class="attr-name token">step</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>1<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>n1<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>age<span class="punctuation token">"</span></span> + <span class="attr-name token">pattern</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>\d+<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>t1<span class="punctuation token">"</span></span><span class="punctuation token">>Quel est votre fruit </span></span>favori ?<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>abbr</span> <span class="attr-name token">title</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>Ce champ est obligatoire<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>*<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>abbr</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>text<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>t1<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>fruit<span class="punctuation token">"</span></span> <span class="attr-name token">list</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>l1<span class="punctuation token">"</span></span> <span class="attr-name token">required</span> + <span class="attr-name token">pattern</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>[Bb]anane|[Cc]erise|[Cc]itron|[Ff]raise|[Oo]range|[Pp]omme<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>datalist</span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>l1<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Banane<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Cerise<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">> + </span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">>Citron</span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">> +</span></span> <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">>Fraise</span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Orange<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span><span class="punctuation token">></span></span>Pomme<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>option</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>datalist</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>t2<span class="punctuation token">"</span></span><span class="punctuation token">>Quelle est votre</span></span> adresse électronique ?<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>email<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>t2<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>email<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>label</span> <span class="attr-name token">for</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>t3<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Laissez un court message<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>label</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>textarea</span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>t3<span class="punctuation token">"</span></span> <span class="attr-name token">name</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>msg<span class="punctuation token">"</span></span> <span class="attr-name token">maxlength</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>140<span class="punctuation token">"</span></span> <span class="attr-name token">rows</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>5<span class="punctuation token">"</span></span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>textarea</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>button</span><span class="punctuation token">></span></span>Soumettre<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>button</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>form</span><span class="punctuation token">></span></span></code></pre> + +<pre class="brush: css line-numbers language-css"><code class="language-css"><span class="selector token">body </span><span class="punctuation token">{</span> + <span class="property token">font</span><span class="punctuation token">:</span> <span class="number token">1</span>em sans-serif<span class="punctuation token">;</span> + <span class="property token">padding</span><span class="punctuation token">:</span> <span class="number token">0</span><span class="punctuation token">;</span> + <span class="property token">margin</span> <span class="punctuation token">:</span> <span class="number token">0</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> + +<span class="selector token">form </span><span class="punctuation token">{</span> + <span class="property token">max-width</span><span class="punctuation token">:</span> <span class="number token">300</span>px<span class="punctuation token">;</span> + <span class="property token">margin</span><span class="punctuation token">:</span> <span class="number token">0</span><span class="punctuation token">;</span> + <span class="property token">padding</span><span class="punctuation token">:</span> <span class="number token">0</span> <span class="number token">5</span>px<span class="punctuation token">;</span> +<span class="punctuation token">}</span> + +<span class="selector token">p > label </span><span class="punctuation token">{</span> + <span class="property token">display</span><span class="punctuation token">:</span> block<span class="punctuation token">;</span> +<span class="punctuation token">}</span> + +<span class="selector token">input[type=text], +input[type=email], +input[type=number], +textarea, +fieldset </span><span class="punctuation token">{</span> +<span class="comment token">/* requis pour composer de manière appropriée les éléments + de formulaire sur les navigateurs fondés sur WebKit */</span> + <span class="property token">-webkit-appearance</span><span class="punctuation token">:</span> none<span class="punctuation token">;</span> + + <span class="property token">width</span> <span class="punctuation token">:</span> <span class="number token">100%</span><span class="punctuation token">;</span> + <span class="property token">border</span><span class="punctuation token">:</span> <span class="number token">1</span>px solid <span class="hexcode token">#333</span><span class="punctuation token">;</span> + <span class="property token">margin</span><span class="punctuation token">:</span> <span class="number token">0</span><span class="punctuation token">;</span> + + <span class="property token">font-family</span><span class="punctuation token">:</span> inherit<span class="punctuation token">;</span> + <span class="property token">font-size</span><span class="punctuation token">:</span> <span class="number token">90%</span><span class="punctuation token">;</span> + + <span class="property token">-moz-box-sizing</span><span class="punctuation token">:</span> border-box<span class="punctuation token">;</span> + <span class="property token">box-sizing</span><span class="punctuation token">:</span> border-box<span class="punctuation token">;</span> +<span class="punctuation token">}</span> + +<span class="selector token">input<span class="pseudo-class token">:invalid</span> </span><span class="punctuation token">{</span> + <span class="property token">box-shadow</span><span class="punctuation token">:</span> <span class="number token">0</span> <span class="number token">0</span> <span class="number token">5</span>px <span class="number token">1</span>px red<span class="punctuation token">;</span> +<span class="punctuation token">}</span> + +<span class="selector token">input<span class="pseudo-class token">:focus</span><span class="pseudo-class token">:invalid</span> </span><span class="punctuation token">{</span> + <span class="property token">outline</span><span class="punctuation token">:</span> none<span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<p>{{EmbedLiveSample("Exemple_complet", "100%", 450)}}</p> + + + +<h3 id="Messages_d'erreur_personnalisés">Messages d'erreur personnalisés</h3> + +<p>Comme nous avons vu dans les exemples précédents, à chaque fois qu'un utilisateur tente d'envoyer un formulaire invalide, le navigateur affiche un message d'erreur. La manière dont le message est affiché dépend du navigateur.</p> + +<p>Ces messages automatiques présentent deux inconvénients:</p> + +<ul> + <li>Il n'y a pas de façon standard de changer leur apparence avec CSS.</li> + <li>Ils dépendent des paramètres régionaux du navigateur, ce qui signifie que vous pouvez avoir une page dans une langue mais les messages d'erreurs affichés dans une autre.</li> +</ul> + +<table> + <caption>Versions françaises des navigateurs sur une page en anglais</caption> + <thead> + <tr> + <th scope="col">Navigateur</th> + <th scope="col">Affichage</th> + </tr> + </thead> + <tbody> + <tr> + <td>Firefox 17 (Windows 7)</td> + <td><img alt="Example of an error message with Firefox in French on an English page" src="/files/4329/error-firefox-win7.png" style="height: 97px; width: 228px;"></td> + </tr> + <tr> + <td>Chrome 22 (Windows 7)</td> + <td><img alt="Example of an error message with Chrome in French on an English page" src="/files/4327/error-chrome-win7.png" style="height: 96px; width: 261px;"></td> + </tr> + <tr> + <td>Opera 12.10 (Mac OSX)</td> + <td><img alt="Example of an error message with Opera in French on an English page" src="/files/4331/error-opera-macos.png" style="height: 83px; width: 218px;"></td> + </tr> + </tbody> +</table> + +<p>Pour personnaliser l'apparence et le texte de ces messages, vous devez utiliser JavaScript ; il n'est pas possible de l'implémenter en utilisant uniquement HTML et CSS.</p> + +<p>HMTL5 fournit une <a href="http://www.w3.org/TR/html5/forms.html#the-constraint-validation-api">API de contraintes de validation</a> pour vérifier et personnaliser l'état des élément d'un formulaire. Il est possible, entre autres, de changer le texte des messages d'erreur. Voici un court exemple :</p> + +<pre class="brush: html"><form> + <label for="mail">Pourriez-vous nous fournir une adresse mail ?</label> + <input type="email" id="mail" name="mail"> + <button>Envoyer</button> +</form></pre> + +<p>En JavaScript, il faut appeler la méthode <a href="/en-US/docs/HTML/HTML5/Constraint_validation#Constraint_API's_element.setCustomValidity()" title="/en-US/docs/HTML/HTML5/Constraint_validation#Constraint_API's_element.setCustomValidity()"><code>setCustomValidity()</code></a>:</p> + +<pre class="brush: js">var email = document.getElementById("mail"); + +email.addEventListener("keyup", function (event) { + if(email.validity.typeMismatch) { + email.setCustomValidity("J'attend un e-mail, mon cher !"); + } else { + email.setCustomValidity(""); + } +});</pre> + +<p>{{EmbedLiveSample("Messages_d'erreur_personnalisés", "100%", 50)}}</p> + +<h2 id="Validation_de_formulaires_avec_JavaScript">Validation de formulaires avec JavaScript</h2> + +<p>Si vous souhaitez avoir le contrôle de l'apparence des messages d'erreur, ou si vous voulez gérer le comportement des navigateurs n'ayant pas implémenté la validation de formulaire HTML5, vous n'avez pas d'autre choix que d'utiliser JavaScript.</p> + +<h3 id="API_de_contraintes_de_validation_HTML5">API de contraintes de validation HTML5</h3> + +<p>De plus en plus de navigateurs prennent maintenant en charge l'API de validation des contraintes, et elle devient fiable. Cette API se compose d'un ensemble de méthodes et de propriétés disponibles sur chaque élément de formulaire.</p> + +<p>Propriétés de l'API de validation des contraintes</p> + +<table> + <thead> + <tr> + <th scope="col">Propriétés</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>validationMessage</code></td> + <td>Un message (dans la langue locale) décrivant les contraintes de validation que le contrôle ne satisfait pas (si c'est le cas), ou une chaîne vide si le contrôle n'est pas soumis à validation (<code>willValidate</code> est alors <code>false</code>), ou bien la valeur de l'élément satisfait ses contraintes.</td> + </tr> + <tr> + <td><code>validity</code></td> + <td>Un objet {{domxref("ValidityState")}} qui décrit l'état de validité de l'élément.</td> + </tr> + <tr> + <td><code>validity.customError</code></td> + <td>Renvoie <code>true</code> si l'élément à une erreur personnalisée, <code>false</code> a contrario.</td> + </tr> + <tr> + <td><code>validity.patternMismatch</code></td> + <td>Renvoie <code>true</code> si la valeur de l'élément ne correspond pas au motif fourni, <code>false</code> dans le cas contraire. Si la méthode renvoie <code>true</code>, l'élément fera partie de la pseudo-classe CSS {{cssxref(":invalid")}}.</td> + </tr> + <tr> + <td><code>validity.rangeOverflow</code></td> + <td>Renvoie <code>true</code> si la valeur de l'élément est supérieure au maximum défini, <code>false</code> dans le cas contraire. Si le retour est <code>true</code>, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}.</td> + </tr> + <tr> + <td><code>validity.rangeUnderflow</code></td> + <td>Renvoie <code>true</code> si la valeur de l'élément est plus petite que le minimum défini, <code>false</code> dans le cas contraire. Si le retour est <code>true</code>, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}.</td> + </tr> + <tr> + <td><code>validity.stepMismatch</code></td> + <td>Renvoie <code>true</code> si la valeur de l'élément ne correspond pas aux règles définies par l'attribut <code>step</code>,<code>false</code> a contrario. Si le retour est <code>true</code>, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}.</td> + </tr> + <tr> + <td><code>validity.tooLong</code></td> + <td>Renvoie <code>true</code> si la taille de l'élément est supérieure à la longueur maximum définie, <code>false</code> dans le cas contraire. Si le retour est <code>true</code>, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}.</td> + </tr> + <tr> + <td><code>validity.typeMismatch</code></td> + <td>Renvoie <code>true</code> si la syntaxe de la valeur de l'élément n'est pas correcte ; <code>false</code> dans le cas contraire. Si le retour est <code>true</code>, l'élément sera de la pseudo-classe CSS {{cssxref(":invalid")}}.</td> + </tr> + <tr> + <td><code>validity.valid</code></td> + <td>Renvoie <code>true</code> si la valeur de l'élément n'a pas de problème de validité, sinon <code>false</code>. L'élément sera de la pseudo-classe CSS {{cssxref(":valid")}} si le retour est <code>true</code> ; de la pseudo-classe CSS {{cssxref(":invalid")}} si le retour est <code>false</code>.</td> + </tr> + <tr> + <td><code>validity.valueMissing</code></td> + <td>Renvoie <code>true</code> si l'élément n'a pas de valeur alors que le champ est requis, sinon<code>false</code>. L'élément sera de la pseudo-classe CSS {{cssxref(":invalid")}} si le retour est <code>true</code>.</td> + </tr> + <tr> + <td><code>willValidate</code></td> + <td>Retourne <code>true</code> si l'élément est validé lorsque le formulaire est soumis, <code>false</code> dans le cas contraire.</td> + </tr> + </tbody> +</table> + +<h4 id="Méthodes_de_l'API_de_validation_des_contraintes">Méthodes de l'API de validation des contraintes</h4> + +<table> + <thead> + <tr> + <th scope="col">Méthodes</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>checkValidity()</code></td> + <td>Renvoie <code>true</code> si la valeur de l'élément n'a pas de problème de validation, <code>false</code> autrement. Si l'élément est invalide, cette méthode déclenche aussi un événement {{event("invalid")}} sur cet élément.</td> + </tr> + <tr> + <td><code>setCustomValidity(<em>message</em>)</code></td> + <td>Ajoute un message d'erreur personnalisé à l'élément ; si vous définissez un message d'erreur personnalisé, l'élément est considéré comme invalide, et le message spécifié est affiché. Cela vous permet d'utiliser du code JavaScript pour établir une erreur de validation autre que celles offertes par l'API standard des contraintes de validation. Le message est affiché à l'utilisateur lorsque le problème est rapporté. Si l'argument est une chaîne de caractères vide, l'erreur personnalisée est considérée comme effacée.</td> + </tr> + </tbody> +</table> + +<p>Pour les anciens navigateurs, il existe <a href="https://hyperform.js.org/">une prothèse d'émulation (<em>polyfill</em>) comme Hyperform</a>, pour compenser le défaut de prise en charge de cette API. Comme vous utilisez déjà JavaScript, l'utilisation d'une prethèse d'émulation n'est pas un souci supplémentaire pour la conception ou l'implémentation de votre site ou application Web.</p> + +<h4 id="Exemple_d'utilisation_de_l'API_de_validation_des_contraintes">Exemple d'utilisation de l'API de validation des contraintes</h4> + +<p>Voyons comment utiliser l'API pour créer des messages d'erreur personnalisés. Tout d'abord, le HTML :</p> + +<pre class="brush: html"><form novalidate> + <p> + <label for="mail"> + <span>Veuillez saisir une adresse e-mail :</span> + <input type="email" id="mail" name="mail"> + <span class="error" aria-live="polite"></span> + </label> + <p> + <button>Envoyer</button> +</form></pre> + +<p>Ce formulaire simple utilise l'attribut {{htmlattrxref("novalidate","form")}} pour désactiver la validation automatique par le navigateur ; cela permet donc à notre script d'avoir le contrôle sur la validation. Toutefois, cela ne désactive la prise en charge par l'API de validation des contraintes, ni l'application des pseudo-classes CSS {{cssxref(":valid")}}, {{cssxref(":invalid")}}, {{cssxref(":in-range")}} et {{cssxref(":out-of-range")}}. Cela signifie que, même si le navigateur ne vérifie pas automatiquement la validité du formulaire avant l'envoi des données, vous pouvez toujours effectuer cette validation et définir l'apparence du formulaire par vous-même.</p> + +<p>L'attribut <code><a href="https://developer.mozilla.org/en-US/docs/Accessibility/ARIA/ARIA_Live_Regions">aria-live</a></code> garantit que nos messages d'erreur personnalisés seront affichés à tout le monde, y compris les personnes utilisant des techniques d'assistance comme des lecteurs d'écran.</p> + +<h5 id="CSS">CSS</h5> + +<p>Ce CSS compose le formulaire et les messages d'erreur pour les rendre plus attrayants.</p> + +<pre class="brush: css">/* Juste pour que notre exemple soit plus joli */ +body { + font: 1em sans-serif; + padding: 0; + margin : 0; +} + +form { + max-width: 200px; +} + +p * { + display: block; +} + +input[type=email]{ + -webkit-appearance: none; + + width: 100%; + border: 1px solid #333; + margin: 0; + + font-family: inherit; + font-size: 90%; + + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* Voici notre composition pour les champs invalides */ +input:invalid{ + border-color: #900; + background-color: #FDD; +} + +input:focus:invalid { + outline: none; +} + +/* Voici la mise en forme pour les erreurs */ +.error { + width : 100%; + padding: 0; + + font-size: 80%; + color: white; + background-color: #900; + border-radius: 0 0 5px 5px; + + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.error.active { + padding: 0.3em; +}</pre> + +<h5 id="JavaScript">JavaScript</h5> + +<p>Le code JavaScript suivant gère la validation personnalisée des erreurs.</p> + +<pre class="brush: js">// Il y a plusieurs façon de sélectionner un nœud DOM ; ici on récupère +// le formulaire et le champ d'e-mail ainsi que l'élément span +// dans lequel on placera le message d'erreur + +var form = document.getElementsByTagName('form')[0]; +var email = document.getElementById('mail'); +var error = document.querySelector('.error'); + +email.addEventListener("input", function (event) { + // Chaque fois que l'utilisateur saisit quelque chose + // on vérifie la validité du champ e-mail. + if (email.validity.valid) { + // S'il y a un message d'erreur affiché et que le champ + // est valide, on retire l'erreur + error.innerHTML = ""; // On réinitialise le contenu + error.className = "error"; // On réinitialise l'état visuel du message + } +}, false); +form.addEventListener("submit", function (event) { + // Chaque fois que l'utilisateur tente d'envoyer les données + // on vérifie que le champ email est valide. + if (!email.validity.valid) { + + // S'il est invalide, on affiche un message d'erreur personnalisé + error.innerHTML = "J'attends une adresse e-mail correcte, mon cher !"; + error.className = "error active"; + // Et on empêche l'envoi des données du formulaire + event.preventDefault(); + } +}, false);</pre> + +<p>Voici le résultat:</p> + +<p>{{EmbedLiveSample("Exemple_d'utilisation_de_l'API_de_validation_des_contraintes", "100%", 130)}}</p> + +<p>L'API de validation des contraintes fournit un outil puissant pour gérer la validation des formulaires, en vous laissant un contrôle sur l'interface utilisateur bien supérieur à ce que vous auriez pu avoir avec uniquement HTML et CSS. </p> + +<h3 id="Valider_des_formulaires_sans_API_intégrée">Valider des formulaires sans API intégrée</h3> + +<p>Il arrive parfois, comme c'est le cas avec des navigateurs anciens ou de <a href="/fr/docs/HTML/Forms/How_to_build_custom_form_widgets">widgets personnalisés</a>, de ne pas pouvoir (ou vouloir) utiliser l'API de validation des contraintes. Dans ce cas, vous pourrez toujours utiliser JavaScript pour valider votre formulaire. Valider un formulaire est plus une question d'interface utilisateur que de réelle validation des données.</p> + +<p>Pour valider un formulaire, vous devez vous poser un certain nombre de questions:</p> + +<dl> + <dt>Quel type de validation dois-je réaliser ?</dt> + <dd>Vous devez déterminer comment valider vos données : opération sur des chaînes de caractères, conversion de type, expressions rationnelles, etc. C'est comme vous voulez. Mais retenez simplement que les données de formulaire sont toujours du texte et sont toujours fournies à vos scripts sous forme de chaînes de caractères.</dd> + <dt>Que dois-je faire si le formulaire n'est pas valide ?</dt> + <dd>C'est clairement une affaire d'interface utilisateur. Vous devez décider comment le formulaire doit se comporter : enverra-t-il quand même les données ? Devriez-vous mettre en évidence les champs qui sont en erreur ? Devriez-vous afficher des messages d'erreur ?</dd> + <dt>Comment puis-je aider l'utilisateur à corriger ses données invalides?</dt> + <dd>Pour limiter la frustration de l'utilisateur, il est très important de fournir autant d'information d'aide que nécessaire pour le guider dans la correction de sa saisie. Vous devriez afficher des suggestions en amont pour que l'utilisateur sache ce qui est attendu, ainsi que des messages d'erreur clairs. Si vous souhaitez vous plonger dans les exigences d'interface utilsateur pour la validation de formulaires, voici quelques articles (en anglais) utiles que vous devriez lire :</dd> + <dd> + <ul> + <li>SmashingMagazine : <a href="http://uxdesign.smashingmagazine.com/2012/06/27/form-field-validation-errors-only-approach/" rel="external" title="http://uxdesign.smashingmagazine.com/2012/06/27/form-field-validation-errors-only-approach/">Form-Field Validation: The Errors-Only Approach</a></li> + <li>SmashingMagazine : <a href="http://www.smashingmagazine.com/2009/07/07/web-form-validation-best-practices-and-tutorials/" rel="external" title="http://www.smashingmagazine.com/2009/07/07/web-form-validation-best-practices-and-tutorials/">Web Form Validation: Best Practices and Tutorials</a></li> + <li>Six Revision : <a href="http://sixrevisions.com/user-interface/best-practices-for-hints-and-validation-in-web-forms/" rel="external" title="http://sixrevisions.com/user-interface/best-practices-for-hints-and-validation-in-web-forms/">Best Practices for Hints and Validation in Web Forms</a></li> + <li>A List Apart : <a href="http://www.alistapart.com/articles/inline-validation-in-web-forms/" rel="external" title="http://www.alistapart.com/articles/inline-validation-in-web-forms/">Inline Validation in Web Forms</a></li> + </ul> + </dd> +</dl> + +<h4 id="Exemple_qui_n'utilise_pas_l'API_de_validation_des_contraintes">Exemple qui n'utilise pas l'API de validation des contraintes</h4> + +<p>Afin d'illustrer le propos, réécrivons le précédent exemple afin qu'il fonctionne avec d'anciens navigateurs:</p> + +<pre class="brush: html"><form> + <p> + <label for="mail"> + <span>Veuillez saisir une adresse e-mail :</span> + <input type="text" class="mail" id="mail" name="mail"> + <span class="error" aria-live="polite"></span> + </label> + <p> + <!-- Certains navigateurs historiques ont besoin de l'attribut + `type` avec la valeur `submit` sur l'élément `button` --> + <button type="submit">Envoyer</button> +</form></pre> + +<p>Comme vous pouvez voir, le HTML est quasiment identique; nous avons juste enlevé les fonctionnalités de validation HTML. Notez que <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a> est une spécification indépendante qui n'est pas spécifiquement liée à HTML5.</p> + +<h5 id="CSS_2">CSS</h5> + +<p>De même, nous n'avons pas eu à changer radicalement les CSS ; nous avons simplement transformé la pseudo-classe {{cssxref(":invalid")}} en une vraie classe et évité d'utiliser le sélecteur d'attribut, qui ne fonctionne pas avec Internet Explorer 6.</p> + +<pre class="brush: css">/* On améliore l'aspect de l'exemple avec ces quelques règles */ +body { + font: 1em sans-serif; + padding: 0; + margin : 0; +} + +form { + max-width: 200px; +} + +p * { + display: block; +} + +input.mail { + -webkit-appearance: none; + + width: 100%; + border: 1px solid #333; + margin: 0; + + font-family: inherit; + font-size: 90%; + + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* Voici les règles de mise en forme pour les champs invalides */ +input.invalid{ + border-color: #900; + background-color: #FDD; +} + +input:focus.invalid { + outline: none; +} + +/* Voici les règles utilisées pour les messages d'erreur */ +.error { + width : 100%; + padding: 0; + + font-size: 80%; + color: white; + background-color: #900; + border-radius: 0 0 5px 5px; + + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.error.active { + padding: 0.3em; +}</pre> + +<h5 id="JavaScript_2">JavaScript</h5> + +<p>Les changements les plus importants sont dans le code JavaScript, qui nécessite bien plus que de simples retouches.</p> + +<pre class="brush: js">// Il existe moins de méthode pour sélectionner un nœud DOM +// avec les navigateurs historiques +var form = document.getElementsByTagName('form')[0]; +var email = document.getElementById('mail'); + +// Ce qui suit est une bidouille pour atteindre le prochain nœud Element dans le DOM +// Attention à cette méthode, elle peut permettre de construire une boucle +// infinie. Pour les navigateurs plus récents, on utilisera element.nextElementSibling +var error = email; +while ((error = error.nextSibling).nodeType != 1); + +// Pour respecter la spécification HTML5 +var emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; + +// De nombreux navigateurs historiques ne supportent pas la méthode +// addEventListener. Voici une méthode simple (il en existe d'autres) +function addEvent(element, event, callback) { + var previousEventCallBack = element["on"+event]; + element["on"+event] = function (e) { + var output = callback(e); + + // Une fonction de rappel (callback) qui renvoie `false` + // pour arrêter la chaîne des callback + // et interrompre l'exécution du callback d'événement. + if (output === false) return false; + + if (typeof previousEventCallBack === 'function') { + output = previousEventCallBack(e); + if(output === false) return false; + } + } +}; + +// On peut désormais reconstruire notre validation de contrainte +// Étant donné qu'on n'utilise pas la pseudo-classe CSS, il faut +// explicitement gérer la classe valid/invalid du champ e-mail +addEvent(window, "load", function () { + // Ici, on teste si le champ est vide (rappel : le champ n'est pas obligatoire) + // S'il ne l'est pas, on vérifie que son contenu est une adresse e-mail valide. + var test = email.value.length === 0 || emailRegExp.test(email.value); + + email.className = test ? "valid" : "invalid"; +}); + +// Ici, on définit ce qui se passe lorsque l'utilisateur +// saisit quelque chose dans le champ +addEvent(email, "keyup", function () { + var test = email.value.length === 0 || emailRegExp.test(email.value); + if (test) { + email.className = "valid"; + error.innerHTML = ""; + error.className = "error"; + } else { + email.className = "invalid"; + } +}); + +// Ici, on définit ce qui se passe lorsque l'utilisateur +// tente d'envoyer les données du formulaire +addEvent(form, "submit", function () { + var test = email.value.length === 0 || emailRegExp.test(email.value); + + if (!test) { + email.className = "invalid"; + error.innerHTML = "Merci d'écrire une adresse e-mail valide."; + error.className = "error active"; + + // Certains navigateurs historiques ne supportent pas + // la méthode event.reventDefault() + return false; + } else { + email.className = "valid"; + error.innerHTML = ""; + error.className = "error"; + } +});</pre> + +<p>Voici le résultat:</p> + +<p>{{EmbedLiveSample("Exemple_qui_n'utilise_pas_l'API_de_validation_des_contraintes", "100%", 130)}}</p> + +<p>Comme vous avez pu le voir, il n'est pas si difficile de créer par soi-même un système de validation. La difficulté consiste à rendre le tout assez générique pour l'utiliser à la fois sur toutes les plateformes et pour chaque formulaire que vous pourriez créer. Il existe de nombreuses bibliothèques permettant ce genre de validation de formulaire ; n'hésitez pas à les utiliser. En voici quelques exemples :</p> + +<ul> + <li>Bibliothèques indépendantes : + <ul> + <li><a href="http://rickharrison.github.com/validate.js/" rel="external" title="http://rickharrison.github.com/validate.js/">Validate.js</a></li> + </ul> + </li> + <li>Greffons jQuery : + <ul> + <li><a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/" rel="external" title="http://bassistance.de/jquery-plugins/jquery-plugin-validation/">Validation</a><span style="display: none;"> </span></li> + </ul> + </li> +</ul> + +<h4 id="Validation_à_distance">Validation à distance</h4> + +<p>Il peut être utile, dans certains cas, d'effectuer une validation à distance. Ce genre de validation est nécessaire lorsque les données saisies par l'utilisateur sont liées à des données supplémentaires stockées sur le serveur hébergeant votre application. Prenons par exemple les formulaires d'inscription, pour lesquels on vous demande un nom d'utilisateur. Pour éviter toute duplication d'un nom d'utilisateur, il est plus judicieux d'effectuer une requête AJAX pour vérifier la disponibilté du nom d'utilisateur que de demander à envoyer les données saisies et de renvoyer le formulaire avec une erreur.</p> + +<p>Pour réaliser une telle validation, plusieurs précautions doivent être prises :</p> + +<ul> + <li>Il est nécessaire d'exposer une API et des données ; assurez-vous que ces données ne soient pas critiques.</li> + <li>Un décalage (<em>lag</em>) du réseau nécessite une validtion asynchrone. L'interface utilisateur doit être conçue de façon à pas être bloquée si cette validation n'est pas réalisée correctement.</li> +</ul> + +<h2 id="Conclusion">Conclusion</h2> + +<p>La validation d'un formulaire ne requiert pas de code JavaScript complexe, mais il est nécessaire de penser tout particulièrement à l'utilisateur. Rappelez-vous de toujours aider l'utilisateur à corriger les données qu'il saisit. Pour ce faire, assurez-vous de toujours :</p> + +<ul> + <li>Afficher des messages d'erreur explicites.</li> + <li>Être tolérant sur le format des données à envoyer.</li> + <li>Indiquer exactement où est l'erreur (en particulier pour les formulaires longs).</li> +</ul> + +<p>{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires", "Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés", "Web/Guide/HTML/Formulaires")}}</p> + +<h2 id="Dans_ce_module">Dans ce module</h2> + +<ul> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Mon_premier_formulaire_HTML">Mon premier formulaire HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_structurer_un_formulaire_HTML"><span>Comment structurer un formulaire HTML</span></a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs">Les widgets natifs pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Envoyer_et_extraire_les_données_des_formulaires">Envoi des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">Validation des données de formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés">Comment construire des widgets personnalisés pour formulaire</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Sending_forms_through_JavaScript">Envoi de formulaires à l'aide du JavaScript</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/HTML_forms_in_legacy_browsers">Formulaires HTML dans les navigateurs anciens</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML">Mise en forme des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms">Mise en forme avancée des formulaires HTML</a></li> + <li><a href="/fr/docs/Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets">Table de compatibilité des propriétés pour les widgets de formulaire</a></li> +</ul> diff --git a/files/fr/web/guide/html/html5/index.html b/files/fr/web/guide/html/html5/index.html new file mode 100644 index 0000000000..02f73932c6 --- /dev/null +++ b/files/fr/web/guide/html/html5/index.html @@ -0,0 +1,167 @@ +--- +title: HTML5 +slug: Web/Guide/HTML/HTML5 +tags: + - HTML + - HTML5 +translation_of: Web/Guide/HTML/HTML5 +--- +<p><strong>HTML5</strong> est la dernière évolution des standards qui définissent <a href="/fr/docs/HTML" title="/fr/docs/HTML">HTML</a>. Le terme HTML5 regroupe deux concepts différents :</p> + +<p>Il s'agit de la nouvelle version du <em>langage</em> HTML, avec de nouveaux éléments, attributs et comportements ; mais aussi un ensemble plus large de technologies qui permettent des sites web plus variés et puissants, et des applications web. Cet ensemble est parfois appelé <em>HTML5 & Cie</em> et est souvent juste abrégé en <em>HTML5</em>.</p> + +<p>Conçue pour être utilisable par tous les développeurs de l'Open Web, cette page de référence fait le lien vers de nombreuses ressources sur les technologies HTML5 classées dans différents groupes suivant leur(s) fonction(s).</p> + +<ul> + <li><em>Sémantique</em> : permet de décrire plus précisément votre contenu.</li> + <li><em>Connectivité</em> : permet de communiquer avec le serveur d'une façon nouvelle et innovante.</li> + <li><em>Hors-connexion & stockage</em> : permet aux pages web de stocker des données en local, côté client, et de fonctionner plus efficacement hors-connexion.</li> + <li><em>Multimédia</em> : rendre la vidéo et l'audio des citoyens de premier plan sur l'Open Web</li> + <li><em>Rendu 2D/3D et effets</em> : permet des options de présentation bien plus variées.</li> + <li><em>Performance & intégration</em> : offre une puissance bien plus grande et une meilleure utilisation du matériel de l'ordinateur.</li> + <li><em>Accès aux périphériques</em> : permet un usage de périphériques d'entrée et de sortie variés.</li> + <li><em>Style</em> : permet aux auteurs d'écrire des thèmes plus sophistiqués.</li> +</ul> + +<div class="cleared row topicpage-table"> +<div class="section"> +<h2 id="Sémantique" style='margin: 0px 0px 0.25em; font: 200 24px/1 "Bebas Neue", "League Gothic", Haettenschweiler, "Arial Narrow", sans-serif; letter-spacing: 1px; text-transform: uppercase; border: medium none;'><img alt="" src="/files/3827/HTML5_Semantics_512.png" style="height: 64px; padding-right: 0.5em; vertical-align: middle; width: 64px;">Sémantique</h2> + +<dl> + <dt><a href="/fr/HTML/Introduction_à_HTML5" title="fr/HTML/Introduction à HTML5"><strong>Introduction à HTML5</strong></a></dt> + <dd>Cet article vous présente la manière d'utiliser HTML5 dans vos conceptions de sites et d'applications web.</dd> + <dt><a href="/fr/docs/HTML/Sections_and_Outlines_of_an_HTML5_document" title="/fr/docs/HTML/Sections_and_Outlines_of_an_HTML5_document">Sections et structure des documents avec HTML5</a></dt> + <dd>Un aperçu de la nouvelle organisation des documents avec les nouveaux éléments de section en HTML5 : {{HTMLElement("section")}}, {{HTMLElement("article")}}, {{HTMLElement("nav")}}, {{HTMLElement("header")}}, {{HTMLElement("footer")}}, {{HTMLElement("aside")}} et {{HTMLElement("hgroup")}}.</dd> + <dt><a href="/fr/docs/Utilisation_d'audio_et_video_dans_Firefox" title="/fr/docs/Utilisation_d'audio_et_video_dans_Firefox">Utilisation de l'audio et de la video en HTML5</a></dt> + <dd>Les éléments {{HTMLElement("audio")}} et {{HTMLElement("video")}} en HTML5 permettent d'insérer et de manipuler dans vos pages de nouveaux contenus multimédias.</dd> + <dt><a href="/en-US/docs/HTML/Forms_in_HTML" title="/en-US/docs/HTML/Forms_in_HTML">Formulaires en HTML5</a></dt> + <dd>Un aperçu des améliorations apportées aux formulaires en HTML5 : l'API de validation, de nouveaux attributs, de nouvelles valeurs pour l'attribut {{htmlattrxref("type", "input")}} de {{HTMLElement("input")}} et le nouvel élément {{HTMLElement("output")}}.</dd> +</dl> + +<dl> + <dt><a href="/fr/HTML/HTML5/Liste_des_éléments_HTML5" title="fr"><strong>Nouveaux éléments d'HTML5</strong></a></dt> + <dd>En plus des éléments de sections, de média et de formulaires, HTML5 ajoute de nombreux nouveaux éléments, comme {{HTMLElement("mark")}}, {{HTMLElement("figure")}}, {{HTMLElement("figcaption")}}, {{HTMLElement("data")}}, {{HTMLElement("time")}}, {{HTMLElement("output")}}, {{HTMLElement("progress")}}, ou encore {{HTMLElement("meter")}}.</dd> + <dt>Amélioration de {{HTMLElement("iframe")}}</dt> + <dd>En utilisant les attributs {{htmlattrxref("sandbox", "iframe")}}, {{htmlattrxref("seamless", "iframe")}}, et {{htmlattrxref("srcdoc", "iframe")}}, les auteurs peuvent contrôler plus finement la sécurité et l'affichage de l'élément {{HTMLElement("iframe")}}.</dd> + <dt><a href="/en-US/docs/MathML" title="/en-US/docs/MathML">MathML</a></dt> + <dd>Permet d'insérer des formules mathématiques directement dans les pages web.</dd> + <dt><a href="/en-US/docs/HTML/HTML5/HTML5_Parser" title="/en-US/docs/HTML/HTML5/HTML5_Parser">Parseur conforme à HTML5</a></dt> + <dd>Le parseur, qui transforme les octets d'un document HTML en un DOM, a été étendu, et défini maintenant précisément le comportement à utiliser dans les différentes situations, même confronté à du code HTML incorrecte. Ceci lui permet d'être bien plus prévisible et interopérable avec les différents moteurs de navigateur.</dd> +</dl> + +<h2 id="Connectivité" style='margin: 0px 0px 0.25em; font: 200 24px/1 "Bebas Neue", "League Gothic", Haettenschweiler, "Arial Narrow", sans-serif; letter-spacing: 1px; text-transform: uppercase; border: medium none;'><img alt="" src="/files/3839/HTML5_Connectivity_512.png" style="height: 64px; padding-right: 0.5em; vertical-align: middle; width: 64px;">Connectivité</h2> + +<dl> + <dt><a href="/en-US/docs/WebSockets" title="/en-US/docs/WebSockets">Web Sockets</a></dt> + <dd>Permet de créer une connexion permanente entre la page et le serveur, et de cette façon échanger des données non-HTML.</dd> + <dt><a href="/en-US/docs/Server-sent_events/Using_server-sent_events" title="/en-US/docs/Server-sent_events/Using_server-sent_events">Évènements envoyés par le serveur</a></dt> + <dd>Permet à un serveur d'envoyer des évènements au client, au lieu du comportement habituel selon lequel le serveur ne peut envoyer des données qu'en réponse à une demande effectuée par le client.</dd> + <dt><a href="/fr/docs/WebRTC" title="/fr/docs/WebRTC">WebRTC</a></dt> + <dd>RTC veut dire <em>Real-Time Communication</em> (Communication en Temps Réel). Cette technologie permet de connecter différentes personnes et de gérer de la visioconférence directement dans le navigateur, sans modules additionnels ou applications externes.</dd> +</dl> + +<h2 id="Hors-connexion_et_Stockage" style='margin: 0px 0px 0.25em; font: 200 24px/1 "Bebas Neue", "League Gothic", Haettenschweiler, "Arial Narrow", sans-serif; letter-spacing: 1px; text-transform: uppercase; border: medium none;'><img alt="" src="/files/3833/HTML5_Offline_Storage_512.png" style="height: 64px; padding-right: 0.5em; vertical-align: middle; width: 64px;">Hors-connexion et Stockage</h2> + +<dl> + <dt><a href="/fr/docs/Utiliser_Application_Cache" title="/fr/docs/Utiliser_Application_Cache">Ressources hors connexion : l'Application Cache</a></dt> + <dd>Firefox gère complètement la spécification des ressources hors connexion de HTML5.</dd> + <dt><a href="/fr/docs/Évènements_online_et_offline" title="/fr/docs/Évènements_online_et_offline">Évènement online et offline</a></dt> + <dd>Firefox 3 gère les évènements online et offline du WHATWG, qui permettent aux applications web et aux extensions de détecter si une connexion à Internet est active ou non, ainsi que le moment où la connexion et la déconnexion se font.</dd> + <dt><a href="/fr/docs/DOM/Storage" title="fr/DOM/Storage">Stockage de session et persistance côté client du WHATWG (ou DOM Storage)</a></dt> + <dd>Le stockage de session et la persistance côté client permettent aux applications web de stocker des données structurées du côté du client.</dd> + <dt><a href="/fr/docs/IndexedDB" title="/fr/docs/IndexedDB">IndexedDB</a></dt> + <dd>Est un standard web pour stocker dans le navigateur des volumes importants de données structurées, et permettant d'effectuer des recherches rapides dans ces données en utilisant des index.</dd> + <dt><a href="/fr/docs/Using_files_from_web_applications" title="fr/Utilisation de fichiers depuis des applications web">Utilisation de fichiers depuis des applications web</a></dt> + <dd>La gestion de la nouvelle API File d'HTML5 a été ajoutée à Gecko, ce qui permet aux applications web d'accéder à des fichiers locaux sélectionnés par l'utilisateur. Cela comprend la sélection de plusieurs fichiers à l'aide du nouvel attribut {{htmlattrxref("multiple", "input")}} de l'élément HTML <span style="font-family: monospace;">{{HTMLElement("input")}}</span><code> </code>{{htmlattrxref("type", "input")}}<code>="file"</code>.</dd> +</dl> + +<h2 id="Multimédia" style='margin: 0px 0px 0.25em; font: 200 24px/1 "Bebas Neue", "League Gothic", Haettenschweiler, "Arial Narrow", sans-serif; letter-spacing: 1px; text-transform: uppercase; border: medium none;'><img alt="" src="/files/3835/HTML5_Multimedia_512.png" style="height: 64px; padding-right: 0.5em; vertical-align: middle; width: 64px;">Multimédia</h2> + +<dl> + <dt><a href="/fr/docs/Utilisation_d'audio_et_video_dans_Firefox" title="/fr/docs/Utilisation_d'audio_et_video_dans_Firefox">Utilisation de l'audio et de la video en HTML5</a></dt> + <dd>Les éléments {{HTMLElement("audio")}} et {{HTMLElement("video")}} en HTML5 permettent d'insérer et de manipuler dans les pages web de nouveaux contenus multimédia.</dd> + <dt><a href="/fr/docs/WebRTC" title="/fr/docs/WebRTC">WebRTC</a></dt> + <dd>RTC veut dire <em>Real-Time Communication</em> (Communication en Temps Réel). Cette technologie permet de connecter différentes personnes et de gérer de la visioconférence directement dans le navigateur, sans modules additionnels ou applications externes.</dd> + <dt><a href="/en-US/docs/DOM/Using_the_Camera_API" title="/en-US/docs/DOM/Using_the_Camera_API">Utiliser l'API Camera</a></dt> + <dd>Vous permet d'utiliser, manipuler et stocker une image depuis l'appareil photo ou webcam d'un ordinateur / téléphone.</dd> + <dt>Track et WebVTT</dt> + <dd>L'élément {{HTMLElement("track")}} permet de sous-titrer et de chapitrer. <a href="/en-US/docs/HTML/WebVTT" title="/en-US/docs/HTML/WebVTT">WebVTT</a> est un format pour marquer du texte par rapport à une durée.</dd> +</dl> + +<h2 id="3D_Graphiques_et_Effets" style='margin: 0px 0px 0.25em; font: 200 24px/1 "Bebas Neue", "League Gothic", Haettenschweiler, "Arial Narrow", sans-serif; letter-spacing: 1px; text-transform: uppercase; border: medium none;'><img alt="" src="/files/3841/HTML5_3D_Effects_512.png" style="height: 64px; padding-right: 0.5em; vertical-align: middle; width: 64px;">3D, Graphiques et Effets</h2> + +<dl> + <dt><a href="/fr/docs/Tutoriel_canvas" title="/fr/docs/Tutoriel_canvas">Tutoriel Canvas</a></dt> + <dd>Découvrez le nouvel élément {{HTMLElement("canvas")}} et apprennez à dessiner des graphiques et autres objets dans Firefox.</dd> + <dt><a href="/fr/docs/Dessin_de_texte_avec_canvas" title="fr/Dessin de texte avec canvas">API de texte HTML5 pour les éléments <code><canvas></code></a></dt> + <dd>Les éléments {{HTMLElement("canvas")}} gèrent également l'API texte d'HTML5.</dd> + <dt><a href="/fr/docs/WebGL" title="/fr/docs/WebGL">WebGL</a></dt> + <dd>WebGL amène le monde de la 3D au Web, avec une API très proche de OpenGL ES 2.0, et peut-être utilisé dans les éléments {{HTMLElement("canvas")}}.</dd> + <dt><a href="/fr/docs/SVG" title="/fr/docs/SVG">SVG</a></dt> + <dd>Un format d'image vectoriel basé sur XML qui peut être inclus directement dans du HTML.</dd> +</dl> +</div> + +<div class="section"> +<h2 id="Performance_et_Intégration" style='margin: 0px 0px 0.25em; font: 200 24px/1 "Bebas Neue", "League Gothic", Haettenschweiler, "Arial Narrow", sans-serif; letter-spacing: 1px; text-transform: uppercase; border: medium none;'><img alt="" src="/files/3831/HTML5_Performance_512.png" style="height: 64px; padding-right: 0.5em; vertical-align: middle; width: 64px;">Performance et Intégration</h2> + +<dl> + <dt><a href="/en-US/docs/DOM/Using_web_workers" title="/en-US/docs/DOM/Using_web_workers">Web Workers</a></dt> + <dd>Permet de déléguer l'interprétation du JavaScript sur des fils en arrière plan, et évite ainsi le ralentissement des évènements d’intéraction.</dd> + <dt><code><a href="/fr/docs/XMLHttpRequest" title="/fr/docs/XMLHttpRequest">XMLHttpRequest</a> </code>Niveau 2</dt> + <dd>Permet de récupérer de manière asynchrone certaines parties d'une page. Ceci permet d'afficher du contenu dynamique, s'adaptant en fonction du temps et des actions de l'utilisateur. Il s'agit de la technologie derrière l'<a href="/fr/docs/AJAX" title="/fr/docs/AJAX">AJAX</a>.</dd> + <dt>Moteurs JavaScript à compilation JIT (juste à temps)</dt> + <dd>La nouvelle génération de moteurs JavaScript est bien plus puissante et permet de meilleures performances dans l'interprétation du langage.</dd> + <dt><a href="/fr/docs/DOM/manipuler_lhistorique_du_navigateur" title="/fr/docs/DOM/manipuler_lhistorique_du_navigateur">API Historique</a></dt> + <dd>Permet la manipulation de l'historique du navigateur. Ceci est particulièrement utile sur les pages qui chargent du contenu dynamiquement.</dd> + <dt><a href="/fr/docs/HTML/Contenu_editable" title="/fr/docs/HTML/Contenu_editable">L'attribut contentEditable : transformer un site web en un wiki !</a></dt> + <dd>HTML5 a standardisé l'attribut contentEditable : apprenez-en plus sur cette fonctionnalité.</dd> + <dt><a href="/fr/docs/DragDrop/Drag_and_Drop" title="https://developer.mozilla.org/Fr/DragDrop/Drag_and_Drop">Glisser et déposer</a></dt> + <dd>L'API de glisser et déposer HTML5 (drag and drop) permet de faire glisser des éléments au sein d'une page web. C'est aussi une API plus simple utilisable par les extensions et applications basées sur Mozilla.</dd> + <dt><a href="/fr/docs/Gestion_du_focus_en_HTML" title="fr/Gestion du focus en HTML">Gestion du focus en HTML</a></dt> + <dd>Les nouveaux attributs HTML5 <code>activeElement</code> et <code>hasFocus</code> sont gérés.</dd> + <dt><a href="/fr/docs/Gestionnaires_de_protocoles_web" title="fr/Gestionnaires de protocoles web">Gestionnaires de protocoles web</a></dt> + <dd>Il est à présent possible d'enregistrer des applications web en tant que gestionnaires de protocoles à l'aide de la méthode <code>navigator.registerProtocolHandler()</code>.</dd> + <dt><a href="/en-US/docs/DOM/window.requestAnimationFrame" title="/en-US/docs/DOM/window.requestAnimationFrame">requestAnimationFrame</a></dt> + <dd>Permet de contrôler le rendu des animations et ainsi d'obtenir une performance optimale.</dd> + <dt><a href="/en-US/docs/DOM/Using_fullscreen_mode" title="/en-US/docs/DOM/Using_fullscreen_mode">API Plein écran</a></dt> + <dd>Contrôle l'utilisation de la totalité de l'écran pour afficher une page ou une application web sans l'interface du navigateur</dd> + <dt><a href="/en-US/docs/WebAPI/Pointer_Lock" title="/en-US/docs/WebAPI/Pointer_Lock">API Verrouillage de la souris</a></dt> + <dd>Permet de verrouiller la souris sur le contenu, afin que les jeux ou les applications similaires ne perdent pas le focus lorsque la souris quitte la limite de la fenêtre.</dd> + <dt><a href="/fr/docs/Évènements_online_et_offline" title="/fr/docs/Évènements_online_et_offline">Évènement online et offline</a></dt> + <dd>Pour construire de bonnes applications web capables de fonctionner hors connexion, vous avez besoin de savoir quand votre application est déconnectée du réseau. Et forcément, vous avez aussi besoin de savoir quand votre application est de nouveau connectée au réseau.</dd> +</dl> + +<h2 id="Accès_aux_périphériques" style='margin: 0px 0px 0.25em; font: 200 24px/1 "Bebas Neue", "League Gothic", Haettenschweiler, "Arial Narrow", sans-serif; letter-spacing: 1px; text-transform: uppercase; border: medium none;'><img alt="" src="/files/3837/HTML5_Device_Access_512.png" style="height: 64px; padding-right: 0.5em; vertical-align: middle; width: 64px;">Accès aux périphériques</h2> + +<dl> + <dt><a href="/en-US/docs/DOM/Using_the_Camera_API" title="/en-US/docs/DOM/Using_the_Camera_API">Utiliser l'API Camera</a></dt> + <dd>Vous permet d'utiliser, manipuler et stocker une image depuis l'appareil photo ou webcam d'un ordinateur / téléphone.</dd> + <dt><a href="/en-US/docs/Web/Guide/Touch_events" title="/en-US/docs/Web/Guide/Touch_events">Évènements tactiles</a></dt> + <dd>Des gestionnaires pour réagir aux évènements créés par un utilisateur qui touche un écran tactile.</dd> + <dt><a href="/fr/docs/Using_geolocation" title="/fr/docs/Using_geolocation">Utilisation de la Geolocalisation</a></dt> + <dd>Permet au navigateur de situer l'utilisateur en utilisant la géolocalisation.</dd> + <dt><a href="/en-US/docs/WebAPI/Detecting_device_orientation" title="/en-US/docs/WebAPI/Detecting_device_orientation">Détection de l'orientation de l'appareil</a></dt> + <dd>Permet de savoir si l'appareil sur lequel tourne le navigateur change d'orientation. Cela peut être utilisé comme un périphérique d'entrée (par exemple, un jeu peut réagir selon la position de l'appareil), ou pour adapter la mise en page suivant l'orientation de l'appareil (portrait ou paysage).</dd> + <dt><a href="/en-US/docs/WebAPI/Pointer_Lock" title="/en-US/docs/WebAPI/Pointer_Lock">API Verrouillage de la souris</a></dt> + <dd>Permet de verrouiller la souris sur le contenu, afin que les jeux ou les applications similaires ne perdent pas le focus lorsque la souris quitte la limite de la fenêtre.</dd> +</dl> + +<h2 id="Style" style='margin: 0px 0px 0.25em; font: 200 24px/1 "Bebas Neue", "League Gothic", Haettenschweiler, "Arial Narrow", sans-serif; letter-spacing: 1px; text-transform: uppercase; border: medium none;'><img alt="" src="/files/3829/HTML5_Styling_512.png" style="height: 64px; padding-right: 0.5em; vertical-align: middle; width: 64px;">Style</h2> + +<p><a href="/fr/docs/CSS" title="/fr/docs/CSS">CSS</a> a été enrichi pour styler les éléments d'une manière beaucoup plus avancée. Ceci est souvent défini comme le <a href="/en-US/docs/CSS/CSS3" title="/en-US/docs/CSS/CSS3">CSS3</a>, bien que CSS ne soit plus une spécification monolithique et que les différent modules ne soient pas tous au niveau 3 : certains sont au niveau 1, d'autres au niveau 4, mais tous les niveaux intermédiaires sont couverts.</p> + +<dl> + <dt>Nouveaux styles d'arrière-plan</dt> + <dd>Il est maintenant possible créer une ombre pour une boîte en utilisant {{cssxref("box-shadow")}}, et de définir <a href="/en-US/docs/Web/Guide/CSS/Using_multiple_backgrounds" title="/en-US/docs/Web/Guide/CSS/Using_multiple_backgrounds">plusieurs arrière-plans</a>.</dd> + <dt>Des bordures plus classes</dt> + <dd>Il est maintenant non seulement possible d'utiliser des images pour styler les bordures en utilisant {{cssxref("border-image")}}, mais aussi de faire des bords arrondis grâce à la propriété {{cssxref("border-radius")}}.</dd> + <dt>Animer vos styles</dt> + <dd>En utilisant les <a href="/en-US/docs/Web/Guide/CSS/Using_CSS_transitions" title="/en-US/docs/Web/Guide/CSS/Using_CSS_transitions">Transitions CSS</a> pour animer différents états, ou en utilisant les <a href="/fr/docs/CSS/Animations_CSS" title="/fr/docs/CSS/Animations_CSS">Animations CSS</a> pour animer une partie de la page sans un évènement déclencheur, vous pouvez maintenant gérer les mouvements sur votre page.</dd> + <dt>Amélioration de la typographie</dt> + <dd>Les auteurs ont un bien meilleur contrôle sur leur typographie. Ils peuvent contrôler {{cssxref("text-overflow")}} et la <a href="/fr/docs/CSS/hyphens" title="/fr/docs/CSS/hyphens">césure automatique</a>. Ils peuvent rajouter une <a href="/fr/docs/CSS/text-shadow" title="/fr/docs/CSS/text-shadow">ombre</a> et des <a href="/fr/docs/CSS/text-decoration" title="/fr/docs/CSS/text-decoration">décorations</a> plus fines. Des polices personnalisées peuvent être utilisées grâce {{cssxref("@font-face")}}.</dd> + <dt>Nouvelles options de mise en page</dt> + <dd>Pour améliorer la flexibilité de vos designs, deux nouvelles options de mise en page ont été ajoutées : <a href="/fr/docs/CSS/Colonnes_CSS3" title="/fr/docs/CSS/Colonnes_CSS3">Colonnes CSS</a> et <a href="/en-US/docs/Web/Guide/CSS/Flexible_boxes" title="/en-US/docs/Web/Guide/CSS/Flexible_boxes">boîtes flexibles CSS</a>.</dd> +</dl> +</div> +</div> diff --git a/files/fr/web/guide/html/html5/liste_des_éléments_html5/index.html b/files/fr/web/guide/html/html5/liste_des_éléments_html5/index.html new file mode 100644 index 0000000000..8e339c8a6f --- /dev/null +++ b/files/fr/web/guide/html/html5/liste_des_éléments_html5/index.html @@ -0,0 +1,579 @@ +--- +title: Liste des éléments HTML5 +slug: Web/Guide/HTML/HTML5/Liste_des_éléments_HTML5 +tags: + - Débutant + - Guide + - HTML + - HTML5 + - Web +translation_of: Web/HTML/Element +--- +<p>Cette Page n'est pas encore complète.</p> + +<p>Travail progressif basé sur document de travail en court à <a class="external" href="http://www.whatwg.org/specs/web-apps/current-work/multipage/" rel="external" title="http://www.whatwg.org/specs/web-apps/current-work/multipage/">http://www.whatwg.org/specs/web-apps/current-work/multipage/</a>.</p> + +<h3 id="Élément_racine" style="">Élément racine</h3> + +<p>Les éléments racines définissent la structure d'un document HTML. Ils sont présents dans chacune des pages web et se situent à la suite de la déclaration doctype à la première ligne du document HTML. Les éléments de page sont placés à l'intérieur des balises ouvrante <html> et fermante </html>.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Balise</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ HTMLElement("html") }}</td> + <td>L'<em>élément HTML racine</em> (<strong><code><html></code></strong>) représente la racine du document HTML. Tout autre élément est un descendant de cet élément racine.</td> + </tr> + </tbody> +</table> + +<h3 id="Métadonnées_du_document">Métadonnées du document</h3> + +<p>Les méta-données contiennent les informations liées à la page telles que les styles de présentation et les scripts. Les méta-données de style et de scripts peuvent être définies au sein de la page web ou via un lien pointant vers un fichier.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Balise</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ HTMLElement("head") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("title") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("base") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("link") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("meta") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("style") }}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Gestion_des_scripts">Gestion des scripts</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Balise</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ HTMLElement("script") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("noscript") }}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Sections">Sections</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Balise</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ HTMLElement("body") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("section") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("nav") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("article") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("aside") }}</td> + <td> </td> + </tr> + <tr> + <td><a href="/fr/HTML/Element/Heading_Elements" title="Elementy blokowe"><code><h1>,<h2>,<h3>,<h4>,<h5>,<h6></code></a></td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("hgroup") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("header") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("footer") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("address") }}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Contenu_de_type_bloc">Contenu de type bloc</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Balise</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ HTMLElement("p") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("hr") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("pre") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("blockquote") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("ol") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("ul") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("li") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("dl") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("dt") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("dd") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("figure") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("figcaption") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("div") }}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Les_sémantiques_à_un_niveau_textuel">Les sémantiques à un niveau textuel</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Balise</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ HTMLElement("a") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("em") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("strong") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("small") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("s") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("cite") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("q") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("dfn") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("abbr") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("data") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("time") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("code") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("var") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("samp") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("kbd") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("sub") }},{{ HTMLElement("sup") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("i") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("b") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("u") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("mark") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("ruby") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("rt") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("rp") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("bdi") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("bdo") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("span") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("br") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("wbr") }}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Les_éléments_d'édition">Les éléments d'édition</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Balise</th> + <th scope="col"> </th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ HTMLElement("ins") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("del") }}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Le_contenu_inclus">Le contenu inclus</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Balise</th> + <th scope="col"> </th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ HTMLElement("img") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("iframe") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("object") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("param") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("video") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("audio") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("source") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("track") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("canvas") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("map") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("area") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("svg") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("math") }}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Les_données_tabulaire">Les données tabulaire</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Balise</th> + <th scope="col"> </th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ HTMLElement("table") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("caption") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("colgroup") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("col") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("tbody") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("thead") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("tfoot") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("tr") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("td") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("th") }}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Les_formulaires">Les formulaires</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Balise</th> + <th scope="col"> </th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ HTMLElement("form") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("fieldset") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("legend") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("label") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("input") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("button") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("select") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("datalist") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("optgroup") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("option") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("textarea") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("keygen") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("output") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("progress") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("meter") }}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h3 id="Les_éléments_pour_l'interactivité">Les éléments pour l'interactivité</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Balise</th> + <th scope="col"> </th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ HTMLElement("details") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("summary") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("command") }}</td> + <td> </td> + </tr> + <tr> + <td>{{ HTMLElement("menu") }}</td> + <td> </td> + </tr> + </tbody> +</table> + +<p> </p> diff --git a/files/fr/web/guide/html/liens_email/index.html b/files/fr/web/guide/html/liens_email/index.html new file mode 100644 index 0000000000..54f5d4d9b8 --- /dev/null +++ b/files/fr/web/guide/html/liens_email/index.html @@ -0,0 +1,63 @@ +--- +title: Liens email +slug: Web/Guide/HTML/Liens_email +tags: + - Beginner + - Exemple + - Guide + - HTML + - Web +translation_of: Learn/HTML/Introduction_to_HTML/Creating_hyperlinks#E-mail_links +--- +<p><span class="seoSummary">Il est parfois utile de créer des liens ou des boutons qui nous permettent d'écrire un nouvel e-mail. Par exemple, on peut les utiliser pour créer un bouton « contactez-nous ». Ceci est possible grâce à l'élement HTML {{HTMLElement("a")}} et au format d'URL <code>mailto</code>.</span></p> + +<h2 id="Bases_de_mailto">Bases de <code>mailto</code></h2> + +<p>Dans sa forme la plus basique et la plus utilisée, un lien <code>mailto</code> indique simplement l'adresse e-mail du destinataire. Par exemple :</p> + +<pre class="brush: html notranslate"><a href="mailto:nullepart@mozilla.org">Envoyer l'email nulle part</a></pre> + +<p>Le résultat s'affiche comme ceci : <a href="mailto:nullepart@mozilla.org">Envoyer l'email nulle part</a>.</p> + +<p>En réalité, l'adresse e-mail est optionelle. Si on ne l'ajoute pas (le {{htmlattrxref("href", "a")}} contiendra simplement « mailto: »), une nouvelle fenêtre du client de messagerie de l'utilisateur s'ouvrira, sans destinataire spécifié. Cela peut être utile dans le cas d'un bouton « Partager » où l'utilisateur sélectionnera les personnes auxquelles il veut envoyer un e-mail.</p> + +<h2 id="Précisions">Précisions</h2> + +<p>En plus de l'adresse e-mail, on peut fournir d'autres informations. En effet, n'importe quel champ d'en-tête d'un e-mail standard peut être ajoutée à l'URL <code>mailto</code>. Les plus communément utilisés sont « <code>subject</code> », « <code>cc</code> » et « <code>body</code> » (qui n'est pas réellement un champ d'entête mais qui permet de spécifier un message court pour le nouvel email). Chaque champ et sa valeur sont indiqués comme un terme de requête.</p> + +<div class="note"> +<p><strong>Note :</strong> Les valeurs de chaque champ doivent être codées au <a href="https://en.wikipedia.org/wiki/Percent-encoding">format URL</a>.</p> +</div> + +<h3 id="Échantillons_dURL_mailto">Échantillons d'URL <code>mailto</code></h3> + +<p>Voici quelques échantillons d'URL <code>mailto</code>:</p> + +<ul> + <li><a href="mailto:">mailto:</a></li> + <li><a href="mailto:nullepart@mozilla.org">mailto:nullepart@mozilla.org</a></li> + <li><a href="mailto:nullepart@mozilla.org,personne@mozilla.org">mailto:nullepart@mozilla.org,personne@mozilla.org</a></li> + <li><a href="mailto:nullepart@mozilla.org?cc=personne@mozilla.org">mailto:nullepart@mozilla.org?cc=personne@mozilla.org</a></li> + <li><a href="mailto:nullepart@mozilla.org?cc=personne@mozilla.org&subject=Ceci%20est%20le%20sujet">mailto:nullepart@mozilla.org?cc=personne@mozilla.org&subject=Ceci%20est%20le%20sujet</a></li> +</ul> + +<p>Notez l'utilisation de l'esperluette (&) pour séparer les champs de l'URL <code>mailto</code>. C'est le format standard d'écriture des URL.</p> + +<h3 id="Exemple">Exemple</h3> + +<p>Si vous voulez créer un lien qui permettrait de s'inscrire à une newsletter, vous pouvez utiliser un lien <code>mailto</code> comme ceci :</p> + +<pre class="brush: html notranslate"><a href="mailto:nullepart@mozilla.org?subject=Demande%20inscription%20newsletter&body=Inscrivez-moi%20%C3%A0%20votre%20newsletter%20%21%0D%0A%0D%0ANom%20complet%20%3A%0D%0A%0D%0AO%C3%B9%20avez-vous%20entendu%20parler%20de%20nous%20%3F"> +Inscrivez-vous à notre newsletter +</a></pre> + +<p>Le résultat s'affiche comme ceci : <a href="mailto:nullepart@mozilla.org?subject=Demande%20inscription%20newsletter&body=Inscrivez-moi%20%C3%A0%20votre%20newsletter%20%21%0D%0A%0D%0ANom%20complet%20%3A%0D%0A%0D%0AO%C3%B9%20avez-vous%20entendu%20parler%20de%20nous%20%3F">Inscrivez-vous à notre newsletter</a>.</p> + +<section id="Quick_Links"> +<ol> + <li>{{HTMLElement("a")}}</li> + <li>{{RFC(6068, "The 'mailto' URI Scheme")}}</li> + <li>{{RFC(5322, "Internet Message Format")}}</li> + <li><a href="http://www.url-encode-decode.com/">Encodage/décodage d'URL en ligne</a></li> +</ol> +</section> diff --git a/files/fr/web/guide/index.html b/files/fr/web/guide/index.html new file mode 100644 index 0000000000..54392f7516 --- /dev/null +++ b/files/fr/web/guide/index.html @@ -0,0 +1,66 @@ +--- +title: Guides pour les développeurs du Web +slug: Web/Guide +tags: + - Guide + - Landing + - Web +translation_of: Web/Guide +--- +<p><strong>Ces articles sont des tutoriels et guides pratiques permettant d'utiliser certaines API et technologies web.</strong></p> + +<div class="row topicpage-table"> +<div class="section"> +<dl> + <dt class="landingPageList"><a href="/fr/docs/Apprendre/HTML">Apprendre - HTML</a></dt> + <dd class="landingPageList"><em>HyperText Markup Language</em> (HTML) est le langage de base pour la grande partie du contenu web. La plupart de ce que vous voyez à l'écran est décrit en HTML.</dd> + <dt class="landingPageList"><a href="/fr/docs/Apprendre/CSS">Apprendre - CSS</a></dt> + <dd class="landingPageList"><em>Cascading Style Sheets</em> (CSS) est un langage de feuille de styles utilisé afin de définir la présentation d'un document écrit en HTML.</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/Audio_and_video_delivery">Fournir de l'audio et/ou de la vidéo</a></dt> + <dd class="landingPageList">Il est possible d'intégrer de l'audio et de la vidéo à du contenu web de différentes façons : que ce soit des fichiers statiques ou des flux adaptatifs. Cet article est une introduction à ces différentes méthodes et à la compatibilité pour les principaux navigateurs web.</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/Audio_and_video_manipulation">Manipuler des données audio ou vidéo</a></dt> + <dd class="landingPageList">Il est possible de combiner les technologies web et les médias afin de créer de nouveaux usages. Dans cet article, nous verrons comment utiliser des technologies web telles que {{htmlelement("canvas")}}, <a href="/fr/docs/Web/WebGL">WebGL</a> ou l'API <a href="/fr/docs/Web/API/Web_Audio_API">Web Audio</a> afin de modifier les fichiers audio ou vidéo directement (en ajoutant des effets de réverbération ou des filtres de couleurs).</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/Events">Guide sur les évènements</a></dt> + <dd class="landingPageList">Les évènements peuvent désigner deux concepts : un patron de conception permettant de gérer de façon asynchrone ce qui se produit lors de la vue d'une page web d'une part et la liste, les noms et les caractéristiques desdits évènements d'autre part.</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/AJAX">AJAX</a></dt> + <dd class="landingPageList">AJAX est un terme regroupant différentes technologies qui permettent aux applications web d'appliquer des mises à jour incrémentales au contenu de la page sans mettre à jour l'intégralité de la page. Cela permet d'obtenir des applications plus rapides et plus réactives.</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/Graphics">Les graphismes sur le Web</a></dt> + <dd class="landingPageList">Les sites et applications web modernes utilisent généralement des graphismes (avec différents degrés de sophistication).</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/API">Guide pour les API web</a></dt> + <dd class="landingPageList">Une liste de l'ensemble des API web et de leur rôle.</dd> + <dt><a href="/fr/docs/JavaScript" title="/fr/docs/JavaScript">JavaScript</a></dt> + <dd>JavaScript est un langage de script notamment utilisé pour créer des applications sur le Web.</dd> + <dt class="landingPageList"><a href="/fr/docs/Localizations_and_character_encodings">Localisations et encodages</a></dt> + <dd class="landingPageList">En interne, les navigateurs traitent le texte en Unicode. Toutefois, la façon de représenter les caractères sous forme d'octets (l'encodage) est utilisée lors du transfert du texte sur le réseau vers le navigateur. La <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#charset">spécification HTML recommande l'usage de l'encodage UTF-8</a> (qui peut représenter l'ensemble des caractères Unicode). Quel que soit l'encodage utilisé, le contenu web doit déclarer l'encodage qu'il utilise.</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/Mobile">Développement web pour mobile</a></dt> + <dd class="landingPageList">Cet article fournit un aperçu des techniques principales utilisées pour concevoir des sites web qui fonctionnent correctement sur les appareils mobiles. Voir aussi <a href="/fr/docs/Mozilla/Firefox_pour_Android">Firefox for Android</a>.</dd> +</dl> +</div> + +<div class="section"> +<dl> + <dt class="landingPageList"><a href="/fr/Apps/Progressive#Core_PWA_guides">Applications web progressives (PWA)</a></dt> + <dd class="landingPageList">Les applications web progressives (aussi appelées PWA) utilisent des API web modernes ainsi que des techniques d'amélioration progressive afin de créer des applications web fonctionnant sur différentes plateformes. Ces applications fonctionnent sur différents appareils et fournissent certaines fonctionnalités les rapprochant des applications natives. Dans ce guide, nous verrons ce qu'il vous faut savoir à propos des PWA.</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/Performance">Optimisation et performance</a></dt> + <dd class="landingPageList">Lorsqu'on construit des sites et applications web, il est crucial que le contenu soit fourni rapidement et efficacement. Ainsi, votre site ou application fonctionnera au mieux, que ce soit sur un PC puissant ou sur un appareil mobile potentiellement plus léger.</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/Parsing_and_serializing_XML">Analyser et sérialiser du XML</a></dt> + <dd class="landingPageList">La plateforme web fournit différentes méthodes pour analyser (<em>parsing</em>) et sérialiser du XML dont chacune a ses avantages et ses inconvénients.</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/WOFF"><em>Web Open Font Format</em> (WOFF)</a></dt> + <dd class="landingPageList">Le format WOFF (<em>Web Open Font Format</em>) est un format pour représenter des polices de caractères afin de les utiliser sur le Web.</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/Unicode_Bidrectional_Text_Algorithm">Algorithme de texte Unicode bidirectionnel (BiDi)</a></dt> + <dd class="landingPageList">L'algorithme Unicode® BiDi fait partie du standard Unicode. Il décrit la façon dont le navigateur doit ordonner les caractères lorsqu'il affiche du texte Unicode. Ce guide présente l'algorithme en général et la façon dont il s'applique au contenu que vous créez. Cela s'avère particulièrement utile lorsque vous concevez et implémentez des systèmes avec une localisation et une internationalisation.</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/Using_FormData_Objects">Manipuler les objets <code>FormData</code></a></dt> + <dd class="landingPageList">L'objet <a href="https://developer.mozilla.org/en/DOM/XMLHttpRequest/FormData"><code>FormData</code></a> permet de compiler un ensemble de paires de clés/valeurs et de l'envoyer via une <code>XMLHttpRequest</code>. Son but principal est d'envoyer des données de formulaire mais il peut être utilisé sans formulaire afin de transmettre des données utilisant des clés. Le format de la transmission est identique à ce qui serait utilisé par la méthode <code>submit()</code> d'un formulaire si l'encodage de celui-ci valait <code>"multipart/form-data"</code>.</dd> + <dt class="landingPageList"><a href="/fr/docs/Web/Guide/User_input_methods">Gérer la saisie de l'utilisateur et les contrôles</a></dt> + <dd class="landingPageList">Sur les sites et applications web, un utilisateur peut interagir avec sa souris et son clavier mais aussi avec d'autres outils (écran tactile par exemple). Cet article fournit quelques recommandations sur la gestion de la saisie de l'utilisateur pour les applications web ainsi qu'une FAQ, des exemples concrets et des liens vers des informations supplémentaires détaillées.</dd> + <dt class="landingPageList"><a href="/fr/docs/Glossaire">Glossaire</a></dt> + <dd class="landingPageList">Définit de nombreux termes techniques relatifs au Web et à Internet.</dd> +</dl> +</div> +</div> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li><a href="/fr/docs/Web/Reference" title="/fr/docs/Web/Reference">Référence pour les développeurs web</a></li> +</ul> diff --git a/files/fr/web/guide/mobile/index.html b/files/fr/web/guide/mobile/index.html new file mode 100644 index 0000000000..8cc4376982 --- /dev/null +++ b/files/fr/web/guide/mobile/index.html @@ -0,0 +1,44 @@ +--- +title: Développement web mobile +slug: Web/Guide/Mobile +translation_of: Web/Guide/Mobile +--- +<p>Cette page fournit un aperçu de certaines des techniques principales nécessaires pour concevoir des sites web qui fonctionneront bien sur les appareils mobiles. Si vous cherchez des informations sur le projet Firefox OS de Mozilla, consultez la page <a href="/fr/Firefox_OS">Firefox OS</a>. Des détails sur <a href="/fr/docs/Mozilla/Firefox_pour_Android" title="Firefox pour Android">Firefox pour Android</a> pourraient également vous intéresser.</p> +<p>Cette page est divisée en deux sections, <a href="#Conception_pour_les_appareils_mobiles">conception pour les appareils mobiles</a> et <a href="#D.C3.A9veloppement_multinavigateur">développement multinavigateur</a>. Consultez également le guide de Jason Grlicky <a href="/fr/docs/Web_Development/Mobile/Mobile-friendliness">mobile-friendliness</a> pour les développeurs web.</p> +<h2 id="Conception_pour_les_appareils_mobiles">Conception pour les appareils mobiles</h2> +<p>Les appareils mobiles ont des caractéristiques physiques assez différentes des ordinateurs portables ou de bureau. Leurs écrans sont généralement plus petits, évidemment, mais ils changent aussi automatiquement l'orientation de l'écran entre portrait et paysage lorsque l'utilisateur les tourne. Ils disposent généralement d'écrans tactiles pour les manipuler. Des API comme la géolocalisation ou l'orientation de l'appareil ne sont pas toujours gérées sur un ordinateur ou y sont beaucoup moins utiles, alors qu'elles donnent aux utilisateurs mobiles de nouvelles manières d'interagir avec votre site.</p> +<h3 id="Gestion_des_petits_écrans">Gestion des petits écrans</h3> +<p>Le <a href="/fr/docs/Développement_Web/Design_web_Responsive">Responsive Web Design</a> est un terme pour un ensemble de techniques permettant à votre site web d'adapter sa disposition lorsque son environnement change ; en particulier la taille et l'orientation de l'écran. Parmi ces techniques :</p> +<ul> + <li>les mises en page CSS fluides, pour permettre à la page de s'adapter progressivement lorsque la taille de la fenêtre de navigation change ;</li> + <li>l'utilisation de <a href="/fr/docs/CSS/Media_queries">media queries</a> pour inclure des règles CSS conditionnelles appropriées pour la <a href="/fr/docs/CSS/Media_queries#width">largeur</a> et la <a href="/fr/docs/CSS/Media_queries#height">hauteur</a> de l'écran.</li> +</ul> +<p>La <a href="/fr/docs/Mozilla/Mobile/Balise_meta_viewport">balise meta <em>viewport</em></a> indique au navigateur d'afficher votre site à l'échelle appropriée pour l'appareil de l'utilisateur.</p> +<h3 id="Gestion_des_écrans_tactiles">Gestion des écrans tactiles</h3> +<p>Pour utiliser un écran tactile, vous devrez travailler avec les <a href="/fr/docs/Web/Guide/DOM/Events/Touch_events">évènements DOM Touch</a>. Vous n'aurez pas la possibilité d'utiliser la pseudo-classe <a href="/fr/docs/CSS/:hover">CSS :hover</a> et devrez concevoir les éléments cliquables comme les boutons de manière à prendre en compte le fait que les doigts sont plus gros qu'un pointeur de souris. Consultez cet article concernant la <a class="external" href="http://www.whatcreative.co.uk/blog/tips/designing-for-touch-screen/">conception pour écrans tactiles</a>.</p> +<p>Vous pouvez utiliser la media query <a href="/fr/docs/CSS/Media_queries#-moz-touch-enabled">-moz-touch-enabled</a> pour charger un style CSS différent sur un appareil tactile.</p> +<h3 id="Optimisation_des_images">Optimisation des images</h3> +<p>Pour aider les utilisateurs dont les appareils ont une bande passante faible ou coûteuse, vous pouvez optimiser les images en ne chargeant que celles qui sont appropriées pour la taille et la résolution de l'écran. Ceci peut se faire en CSS selon la <a href="/fr/docs/CSS/Media_queries#height">hauteur</a>, la <a href="/fr/docs/CSS/Media_queries#width">largeur</a> et la <a href="/fr/docs/CSS/Media_queries#-moz-device-pixel-ratio">densité en pixels</a>.</p> +<p>Il est également possible d'utiliser des propriétés CSS pour concevoir des effets visuels comme des <a href="/fr/docs/CSS/Utilisation_de_dégradés_CSS">dégradés</a> et des <a href="/fr/docs/CSS/box-shadow">ombres</a> sans utiliser d'images.</p> +<h3 id="API_mobiles">API mobiles</h3> +<p>Enfin, vous pourrez tirer partir des nouvelles possibilités offertes par les appareils mobiles, comme l'<a href="/fr/docs/WebAPI/Detecting_device_orientation">orientation</a> et la <a href="/fr/docs/Using_geolocation">géolocalisation</a>.</p> +<h2 id="Développement_multinavigateur">Développement multinavigateur</h2> +<h3 id="Écriture_de_code_multinavigateur">Écriture de code multinavigateur</h3> +<p>Pour créer des sites web qui fonctionneront de manière acceptable sur différents navigateurs mobiles :</p> +<ul> + <li>Essayez d'éviter les fonctionnalités spécifiques à un navigateur, comme les propriétés CSS préfixées par le moteur de rendu.</li> + <li>Si vous avez besoin de ces fonctionnalités, vérifiez si d'autres navigateurs disposent de leurs propres versions de ces fonctionnalités, et traitez-les de la même manière.</li> + <li>Pour les navigateurs qui ne gèrent pas du tout ces fonctionnalités, fournissez une alternative acceptable.</li> +</ul> +<p>Par exemple, si vous prévoyez un fond avec dégradé de couleurs sur une zone de texte avec une propriété préfixée comme <code>-webkit-linear-gradient</code>, il est préférable d'ajouter les autres versions préfixées de la propriété <a href="/fr/docs/CSS/linear-gradient">linear-gradient</a>. Si vous ne le faites pas, assurez-vous au moins que le fond par défaut offre un bon contraste avec le texte : de cette manière la page sera au moins utilisable dans un navigateur qui n'est pas visé par votre règle <code>linear-gradient</code>.</p> +<p>Consultez cette <a href="/fr/docs/Web/CSS/Reference/Mozilla_Extensions">liste des propriétés spécifiques à Gecko</a>, cette liste de <a href="/fr/docs/Web/CSS/Reference/Webkit_Extensions">propriétés spécifiques à WebKit</a>, ainsi que le tableau de Peter Beverloo des <a class="external" href="http://peter.sh/experiments/vendor-prefixed-css-property-overview/">propriétés spécifiques des moteurs de rendu des navigateurs</a>.</p> +<p>Vous pouvez vous aider d'outils comme <a class="external" href="http://csslint.net/">CSS Lint</a> pour trouver des problèmes de ce genre dans votre code, et de préprocesseurs comme <a class="external" href="http://sass-lang.com/">SASS</a> et <a class="external" href="http://lesscss.org/">LESS</a> pour produire du code multinavigateur.</p> +<h3 id="Attention_avec_la_détection_d'agent_utilisateur">Attention avec la détection d'agent utilisateur</h3> +<p>Il est préférable que les sites web détectent des fonctionnalités spécifiques de l'appareil comme sa taille d'écran et ses capacités tactiles à l'aide des techniques listées ci-dessus, et s'y adaptent en conséquence. Mais parfois ce n'est pas possible et certains sites ont recours à la chaîne d'identification d'agent utilisateur (user agent) pour essayer de faire la distinction entre ordinateurs de bureau, tablettes et téléphones afin de servir un type de contenu différent à chaque type d'appareil.</p> +<p>Si vous faites cela, assurez-vous que votre algorithme est correct et que vous ne fournissez pas le mauvais type de contenu à un appareil parce que vous ne traitez pas la chaîne d'identification d'un navigateur particulier. Consultez ce <a href="/fr/docs/Browser_detection_using_the_user_agent#Mobile.2C_Tablet_or_Desktop">guide d'utilisation de la chaîne user agent pour déteminer le type d'appareil</a>.</p> +<h3 id="Test_sur_plusieurs_navigateurs">Test sur plusieurs navigateurs</h3> +<p>Testez votre site web sur plusieurs navigateurs. Cela veut dire aussi tester sur plusieurs plateformes — au moins iOS et Android.</p> +<ul> + <li>testez Safari sur l'iPhone avec <a class="link-https" href="https://developer.apple.com/devcenter/ios/index.action">iOS simulator</a></li> + <li>testez Opera et Firefox avec le <a class="link-https" href="https://developer.android.com/sdk/index.html">SDK Android</a>. Consultez ces instructions pour <a class="link-https" href="https://wiki.mozilla.org/Mobile/Fennec/Android/Emulator">lancer Firefox pour Android avec l'émulateur Android</a>.</li> +</ul> diff --git a/files/fr/web/guide/performance/index.html b/files/fr/web/guide/performance/index.html new file mode 100644 index 0000000000..5c2605f1aa --- /dev/null +++ b/files/fr/web/guide/performance/index.html @@ -0,0 +1,20 @@ +--- +title: Optimisation et performances +slug: Web/Guide/Performance +tags: + - Optimisation + - Performances web + - Web +translation_of: Web/Guide/Performance +--- +<p>Lorsque l’on créent des sites et des applications internet modernes, il est important que notre code soit performant. C’est-à-dire, le faire fonctionner rapidement et efficacement. Lui permettant ainsi de fonctionner aussi efficacement à la fois pour les utilisateurs de puissants systèmes de bureau et pour les appareils portables ayant moins de puissance. On appel cela le PageSpeed Optimization (optimisation de la vitesse de chargement de pages web). Il y a plusieurs outils disponibles pour vérifiez les performances de chargement d’un site ou de blog internet. Les plus connus sont listés ci-dessous : </p> + +<ul> + <li><a href="https://developers.google.com/speed/pagespeed/insights/">Google PageSpeed Insights</a></li> + <li><a href="https://www.pingdom.com">Pingdome - Website Performance Monitoring</a></li> + <li><a href="http://yslow.org/">ySlow</a></li> +</ul> + +<p>Les sites internet statiques en HTML ont besoins, pour améliorer leurs performances, de techniques manuelles d’optimisation. Plusieurs produits logiciels open source à l’instar de WordPress, ont eux des plugins disponibles pour permettre aux propriétaires de sites web d’optimisez leurs performances web. <a href="https://codecanyon.net/item/wp-super-charge/17091749">WP Super Charge</a> est un des plugins disponible sur la boutique de WordPress, il permet à l’utilisateur d’optimisez les performances de son site en un clic.</p> + +<p>{{LandingPageListSubpages}}</p> diff --git a/files/fr/web/guide/user_input_methods/index.html b/files/fr/web/guide/user_input_methods/index.html new file mode 100644 index 0000000000..286b5940c5 --- /dev/null +++ b/files/fr/web/guide/user_input_methods/index.html @@ -0,0 +1,188 @@ +--- +title: Entrées utilisateur et méthodes +slug: Web/Guide/User_input_methods +translation_of: Web/Guide/User_input_methods +--- +<div class="summary"> +<p><span class="seoSummary">Les entrées utilisateur modernes vont au-delà du simple clavier et souris: pensez aux écrans tactiles par exemple. Cet article fournit des recommendations pour gérer les entrées utilisateur et implémenter les contrôles des Open Web Apps, ainsi que des FAQs, des exemples concrets, et des liens pour ceux qui ont besoin d'informations supplémentaires sur les technologies utilisées. Les APIs et événements abordés sont en autre <a href="/fr/docs/Web/Guide/DOM/Events/Touch_events">les événements tactiles</a>, <a href="/fr/docs/WebAPI/Pointer_Lock">l'API Pointer Lock</a>, <a href="/fr/docs/Web/API/CSS_Object_Model/Managing_screen_orientation">l'API Screen Orientation</a>, <a href="/fr/docs/Web/Guide/DOM/Using_full_screen_mode">l'API Fullscreen</a> et <a href="/fr/docs/Web/API/API_HTML_Drag_and_Drop">Drag & Drop</a>.</span></p> +</div> + +<h2 id="Workflow_entrées_utilisateur_et_contrôles">Workflow entrées utilisateur et contrôles</h2> + +<p>La diagramme suivant illustre le déroulement des opérations typique pour implémenter les mécanismes d'entrée utilisateur:</p> + +<p style="text-align: center;"><img alt="" src="https://mdn.mozillademos.org/files/8085/user-input-and-controls.png" style="height: 86px; width: 303px;"></p> + +<p>Tout d'abord vous devez décider quels mécanismes en entrées vous voulez prendre en charge dans votre application: souris, clavier, doigt, etc. Une fois que vous avez décidé, vous pouvez les contrôler en utilisant les outils offerts par la plateforme web ou par des bibliothèques JavaScript.</p> + +<h2 id="Recommandations">Recommandations</h2> + +<p>Les mécanismes en entrées dépendent des capacités de l'appareil qui exécute l'application:</p> + +<ul> + <li>Certains appareils ont des écrans tactiles: le plateforme web dispose des <a href="/fr/docs/Web/Guide/DOM/Events/Touch_events">événements tactiles</a> pour interpréter l'activité du doigt sur les interfaces tactiles.</li> + <li>Pour les appareils ayant une souris/pavé tactile comme méthode de pointage, l'<a href="/fr/docs/WebAPI/Pointer_Lock">API Pointer Lock</a> aide à implémenter un jeu 3D à la première personne ou toute autre application nécessisant un contrôle total du dispositif de pointage. L'<a href="/fr/docs/Web/Guide/DOM/Using_full_screen_mode">API Fullscreen</a> quant à elle aide à afficher l'application en mode plein écran.</li> + <li>En utilisant les fonctionnalités telles que les éléments <a href="/fr/docs/Web/HTML/Contenu_editable">contentEditable</a>, vous pouvez implémenter des éditeurs rich-text rapidement et avec <a href="/fr/docs/Web/API/API_HTML_Drag_and_Drop">Drag&Drop</a> vous pouvez laisser les utilisateurs déplacer des éléments dans votre application. Quand l'orientation de l'écran a de l'importance pour votre application, vous pouvez lire l'orientation de l'écran à travers l'<a href="/fr/docs/Web/API/CSS_Object_Model/Managing_screen_orientation">API Screen Orientation</a> et verrouiller l'écran dans un sens.</li> + <li>Vous devriez toujours être attentif à l'accessibilité du clavier quand c'est approprié — beaucoup d'utilisateurs web utilisent uniquement le clavier pour naviger sur les sites web et applications, et les bloquer hors de votre fonctionnalité est une mauvaise idée.</li> +</ul> + +<p>Vous trouverez ci-dessous un ensemble de recommandations et meilleures pratiques pour utiliser de tels outils dans des Open Web Apps.</p> + +<h3 id="Décidez_quel_mécanisme_en_entrée_vous_utilisez">Décidez quel mécanisme en entrée vous utilisez</h3> + +<h4 id="Clavier">Clavier</h4> + +<p>La saisie du clavier peut être contrôlée par votre application. Par exemple, si vous voulez ajouter des contrôles déclenchés quand des touches sont pressées, vous devez ajouter un gestionnaire d'événement sur l'objet window:</p> + +<pre class="brush: js">window.addEventListener("keydown", handleKeyDown, true); +window.addEventListener("keyup", handleKeyUp, true);</pre> + +<p>où <code>handleKeyDown</code> et <code>handleKeyUp</code> sont des fonctions implémentant les contrôles sur les événements <code>keydown</code> et <code>keyup</code>.</p> + +<div class="note"> +<p><strong>Note</strong>: Jetez un coup d'oeil à la <a href="/fr/docs/Web/Events">Référence des événements</a> et au guide {{domxref("KeyboardEvent")}} pour en savoir plus sur les événements de clavier.</p> +</div> + +<h4 id="Souris">Souris</h4> + +<p>Les événements qui se produisent quand l'utilisateur interagit avec un appareil de pointage comme une souris sont représentés par l'interface DOM {{domxref("MouseEvent")}}. Les événements de souris les plus communs sont <a href="/fr/docs/Web/Events/click"><code>click</code></a>, <a href="/fr/docs/Web/Events/dblclick"><code>dblclick</code></a>, <a href="/fr/docs/Web/Events/mouseup"><code>mouseup</code></a>, et <a href="/fr/docs/Web/Events/mousedown"><code>mousedown</code></a>. La liste de tous les événements souris utilisant l'interface MouseEvent est disponible dans la <a href="/fr/docs/Web/Events">Référence des événements</a>.<br> + <br> + Quand le périphérique d'entrée est une souris, vous pouvez également contrôler les entrées utilisateur avec l'API Pointer Lock et implémenter le Drag & Drop (voir ci-dessous).</p> + +<h4 id="Toucher_du_doigt">Toucher du doigt</h4> + +<p>Quand vous développez des applications web destinées à être installées sur des appareils à écran tactile, il est recommandé de prendre en considération les différentes capacités de l'appareil, en terme de résolution d'écran et d'entrée utilisateur. Les <a href="/fr/docs/Web/Guide/DOM/Events/Touch_events">événements tactiles</a> peuvent vous aider à implémenter des éléments interactifs et des geste d'interactions courants sur les appareils à écran tactile.<br> + <br> + Si vous voulez utiliser les événements tactiles, vous devez ajouter des gestionnaires d'événement et spécifier des fonctions de rappel, appelées quand l'événement est déclenché:</p> + +<pre class="brush: js">element.addEventListener("touchstart", handleStart, false); +element.addEventListener("touchend", handleEnd, false); +element.addEventListener("touchcancel", handleCancel, false); +element.addEventListener("touchend", handleEnd, false); +element.addEventListener("touchmove", handleMove, false);</pre> + +<p>où <code>element</code> est l'élément du DOM sur lequel vous voulez enregistrer les événements tactiles.</p> + +<div class="note"> +<p><strong>Note</strong>: Pour plus d'informations sur ce que vous pouvez faire avec les événements tactiles, lisez le guide des <a href="/fr/docs/Web/Guide/DOM/Events/Touch_events">événements tactiles</a>.</p> +</div> + +<h4 id="Événements_de_pointeur">Événements de pointeur</h4> + +<p>Quand vous avez affaire à des appareils qui incorporent de multiples formes d'entrée, comme la souris, le toucher du doigt et la saisie au stylet, il peut être difficile de développer une solution qui marche pour tous ces mécanismes de contrôle différents. Les <a href="/fr/docs/Web/API/Pointer_events">événements de pointeur</a> aident les développeurs à gérer plus facilement les événements sur les appareils en normalisant le traitement de chacun d'entre eux. Un pointeur peut être n'importe quel contact sur l'écran, fait par le curseur d'une souris, d'un stylo, le toucher (y compris multi-touch) ou autre périphérique d'entrée de pointage. Les événements génériques pour gérer la saisie du pointeur ressemblent beaucoup à ceux pour la souris: <code>pointerdown</code>, <code>pointermove</code>, <code>pointerup</code>, <code>pointerover</code>, <code>pointerout</code>, etc.</p> + +<div class="note"> +<p><strong>Note</strong>: Les événements du pointeur ne sont pas encore beaucoup pris en charge, mais le <a href="https://github.com/mozilla/pointer.js">polyfill pointer.js</a> est disponible sur le compte GitHub de Mozilla.</p> +</div> + +<h3 id="Implémentez_les_contrôles">Implémentez les contrôles</h3> + +<h4 id="Verrouiller_le_pointeur">Verrouiller le pointeur</h4> + +<p>Dans certains cas, typiquement dans le développement de jeux, vous pouvez avoir besoin d'accéder aux événements de la souris même lorsque le curseur dépasse la limite du navigateur ou de l'écran: l'{{domxref("Pointer_Lock_API", "API Pointer Lock")}} vous donne le contrôle total de l'appareil de pointage.</p> + +<p>Voici le code pour demander que le pointeur soit bloqué à l'intérieur d'<code>element</code>:</p> + +<pre class="brush: js">element.requestPointerLock();</pre> + +<div class="note"> +<p><strong>Note</strong>: Pour un tutoriel complet et la référence, lisez notre page {{domxref("Pointer_Lock_API", "Pointer Lock API")}}.</p> +</div> + +<h4 id="Orientation_de_l'écran">Orientation de l'écran</h4> + +<p>Si l'orientation de l'écran est importante pour votre application, vous pouvez lire l'état de l'orientation de l'écran, être informé quand cet état change, et verrouiller l'orientation dans un état spécifique (habituellement portrait ou paysage) à travers l'<a href="/fr/docs/Web/API/CSS_Object_Model/Managing_screen_orientation">API Screen Orientation</a>.</p> + +<p>Les données d'orientation peuvent être récupérées à travers l'attribut {{domxref("screen.orientation")}} ou à travers la media query <a href="/fr/docs/Web/CSS/@media/orientation"><code>orientation</code></a>. Quand <code>screen.orientation</code> change, l'événement {{domxref("screen.orientationchange")}} est declenché sur l'objet screen. Verrouiller l'orientation de l'écran en possible en invoquant la méthode {{domxref("screen.lockOrientation")}}, tandis que la méthode {{domxref("screen.unlockOrientation")}} supprime le verrouillage de l'écran précédemment définit.</p> + +<div class="note"> +<p><strong>Note</strong>: Pour plus d'informations sur l'API Screen Orientation API consultez <a href="/fr/docs/Web/API/CSS_Object_Model/Managing_screen_orientation">Gérer l'orientation de l'écran</a>.</p> +</div> + +<h4 id="Plein_écran">Plein écran</h4> + +<p>Vous pourriez avoir besoin de présenter un élément de votre application (comme une {{ htmlelement("video") }} par exemple) en mode plein écran. Vous pouvez y parvenir en appelant {{domxref("Element.requestFullscreen()")}} sur cet élément. Gardez à l'esprit que beaucoup de navigateurs l'implémentent encore avec un préfixe de fournisseur, vous aurez donc probablement besoin de découper votre code ainsi:</p> + +<pre class="brush: js language-js"><code class="language-js"><span class="keyword token">var</span> elem <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">getElementById<span class="punctuation token">(</span></span><span class="string token">"myvideo"</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="keyword token">if</span> <span class="punctuation token">(</span>elem<span class="punctuation token">.</span>requestFullscreen<span class="punctuation token">)</span> <span class="punctuation token">{</span> + elem<span class="punctuation token">.</span><span class="function token">requestFullscreen<span class="punctuation token">(</span></span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> <span class="keyword token">else</span> <span class="keyword token">if</span> <span class="punctuation token">(</span>elem<span class="punctuation token">.</span>msRequestFullscreen<span class="punctuation token">)</span> <span class="punctuation token">{</span> + elem<span class="punctuation token">.</span><span class="function token">msRequestFullscreen<span class="punctuation token">(</span></span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> <span class="keyword token">else</span> <span class="keyword token">if</span> <span class="punctuation token">(</span>elem<span class="punctuation token">.</span>mozRequestFullScreen<span class="punctuation token">)</span> <span class="punctuation token">{</span> + elem<span class="punctuation token">.</span><span class="function token">mozRequestFullScreen<span class="punctuation token">(</span></span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> <span class="keyword token">else</span> <span class="keyword token">if</span> <span class="punctuation token">(</span>elem<span class="punctuation token">.</span>webkitRequestFullscreen<span class="punctuation token">)</span> <span class="punctuation token">{</span> + elem<span class="punctuation token">.</span><span class="function token">webkitRequestFullscreen<span class="punctuation token">(</span></span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<div class="note"> +<p><strong>Note</strong>: Pour en savoir plus sur la fonctionnalité de plein écran, lisez notre documentation <a href="/fr/docs/Web/Guide/DOM/Using_full_screen_mode">utiliser le plein écran</a>.</p> +</div> + +<h4 id="Drag_Drop">Drag & Drop</h4> + +<p><a href="/fr/docs/Web/API/API_HTML_Drag_and_Drop">Drag & Drop</a> (glisser/déposer) permet à l'utilisateur de votre application de cliquer sur un élément, maintenir le bouton de la souris enfoncé sur cet élément, le faire glisser vers un autre emplacement, et relacher le bouton de la souris pour le déposer à cet emplacement.<br> + <br> + Voici un exemple qui permet à du contenu d'être déplacé:</p> + +<pre class="brush: html"><div draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'Ce texte peut être déplacé')"> + Ce texte <strong>peut</strong> être déplacé. +
</div></pre> + +<p>Ici, on</p> + +<ul> + <li>Définit l'attribut <a href="/fr/docs/Web/HTML/Attributs_universels#attr-dir"><code>draggable</code></a> à vrai pour que l'élément puisse être déplacé.</li> + <li>Ajoute un gestionnaire d'événement <a href="/fr/docs/Web/Events/dragstart"><code>dragstart</code></a> qui définit les données de déplacement à l'intérieur.</li> +</ul> + +<div class="note"> +<p><strong>Note</strong>: Vous pouvez trouver plus d'informations dans la documentation MDN <a href="/fr/docs/Web/API/API_HTML_Drag_and_Drop">Drag & Drop</a>.</p> +</div> + +<h4 id="contentEditable">contentEditable</h4> + +<p>Dans un Open Web App, tout élément DOM peut être rendu directement éditable en utilisant l'attribut <a href="/fr/docs/Web/HTML/Attributs_universels#attr-class"><code>contenteditable</code></a>.</p> + +<pre class="brush: html"><div contenteditable="true"> + Ce texte peut être édité par l'utilisateur. +</div></pre> + +<div class="note"> +<p><strong>Note</strong>: Vous pouvez trouver les informations de compatibilité, des exemples et d'autres ressources dans le guide <a href="/fr/docs/Web/HTML/Contenu_editable">Contenu Éditable</a>.</p> +</div> + +<h2 id="Exemples">Exemples</h2> + +<dl> + <dt><strong><a href="/en/DOM/Touch_events#Example">Suivre plusieurs points de contact à la fois</a></strong></dt> + <dd>Cet exemple permet de gérer un toucher multiple (plusieurs contacts simultanés), permettant ainsi à l'utilisateur de dessiner dans un <code>{{htmlelement("canvas")}}</code> avec plusieurs doigts. Cela ne fonctionne qu'avec les navigateurs supportant les interactions tactiles.</dd> + <dt><strong><a href="/fr/docs/WebAPI/Pointer_Lock#example">Démo de verrouillage de pointeur simple</a></strong></dt> + <dd>Vous avons écrit une démo de verrouillage de pointeur pour vous montrer comment l'utiliser pour mettre en place un système de contrôle simple. Cette démo utilise JavaScript pour dessiner une balle dans un élément <code>{{htmlelement("canvas")}}</code>. Quand vous cliquez sur le canvas, le verrouillage du pointeur est utilisé pour supprimer le curseur de la souris à l'écran et vous permettre de déplacer la balle avec la souris.</dd> + <dt><strong><a href="http://html5demos.com/contenteditable">Démo contentEditable</a></strong></dt> + <dd>Ceci est un exemple qui montre comment contenteditable peut être utilisé pour créer une section de document éditable, et dont l'état est sauvegardé en utilisant <a href="/fr/docs/Web/API/Web_Storage_API">LocalStorage</a>.</dd> +</dl> + +<h2 id="Tutoriels">Tutoriels</h2> + +<ul> + <li><a href="/fr/docs/Web/Guide/DOM/Events/Touch_events">Événement tactiles</a></li> + <li><a href="/fr/docs/Web/API/CSS_Object_Model/Managing_screen_orientation">Gérer l'orientation de l'écran</a></li> + <li><a href="/fr/docs/Web/Guide/DOM/Using_full_screen_mode">Utiliser le mode plein écran</a></li> + <li><a href="/fr/docs/Web/API/HTML_Drag_and_Drop_API/Multiple_items">Drag & Drop de multiples éléments</a></li> + <li><a href="/fr/docs/Web/API/API_HTML_Drag_and_Drop/Op%C3%A9rations_de_glissement">Opérations de glissement</a></li> +</ul> + +<h2 id="Référence">Référence</h2> + +<ul> + <li>{{domxref("MouseEvent")}}</li> + <li>{{domxref("KeyboardEvent")}}</li> + <li><a href="/fr/docs/Web/Guide/DOM/Events/Touch_events">Événements tactiles</a></li> + <li><a href="/fr/docs/WebAPI/Pointer_Lock">Pointer Lock API</a></li> + <li><a href="/fr/docs/Web/API/CSS_Object_Model/Managing_screen_orientation">Screen Orientation API</a></li> + <li><a href="/fr/docs/Web/Guide/DOM/Using_full_screen_mode">Fullscreen API</a></li> + <li><a href="/fr/docs/Web/API/API_HTML_Drag_and_Drop">Drag & Drop</a></li> + <li><a href="/fr/docs/Web/HTML/Contenu_editable">Content Editable</a></li> + <li><a href="https://developer.mozilla.org/en-US/Firefox_OS/Platform/Keyboard_events_in_Firefox_OS_TV">Keyboard events in Firefox OS TV</a></li> + <li><a href="/en-US/docs/Mozilla/Firefox_OS/TVs_connected_devices/TV_remote_control_navigation">Implementing TV remote control navigation</a></li> +</ul> diff --git a/files/fr/web/guide/using_formdata_objects/index.html b/files/fr/web/guide/using_formdata_objects/index.html new file mode 100644 index 0000000000..f284c72df4 --- /dev/null +++ b/files/fr/web/guide/using_formdata_objects/index.html @@ -0,0 +1,140 @@ +--- +title: Utiliser les objets FormData +slug: Web/Guide/Using_FormData_Objects +translation_of: Web/API/FormData/Using_FormData_Objects +--- +<p>L'objet <a href="/en/DOM/XMLHttpRequest/FormData" title="en/DOM/XMLHttpRequest/FormData"><code>FormData</code></a> vous permet de créer un ensemble de paires clef-valeur pour un envoi via <code>XMLHttpRequest</code>. Cet objet est destiné avant tout à l'envoi de données de formulaire, mais il peut être utilisé indépendamment des formulaires afin de transmettre des données associées à une clef. Les données transmises sont dans le même format qu'utiliserait la méthode <code>submit()</code> pour envoyer des données si le type d'encodage du formulaire correspondait à "multipart/form-data".</p> + +<h2 id="Créer_un_objet_FormData_de_zéro">Créer un objet <code>FormData</code> de zéro</h2> + +<p>Vous pouvez créer un objet <code>FormData</code> en l'instanciant puis en lui ajoutant des champs au moyen de la méthode <a href="/en/DOM/XMLHttpRequest/FormData#append()" title="en/XMLHttpRequest/FormData#append()"><code>append()</code></a>, comme ci-dessous :</p> + +<pre class="brush: js">var formData = new FormData(); + +formData.append("username", "Groucho"); +formData.append("accountnum", 123456); // le nombre 123456 est immédiatement converti en la chaîne "123456" + +// Choix de l'utilisateur à partir d'un input HTML de type file... +formData.append("userfile", fileInputElement.files[0]); + +// Pseudo-objet fichier JavaScript... +var content = '<a id="a"><b id="b">hey!</b></a>'; // le corps du nouveau fichier... +var blob = new Blob([content], { type: "text/xml"}); + +formData.append("webmasterfile", blob); + +var request = new XMLHttpRequest(); +request.open("POST", "http://foo.com/submitform.php"); +request.send(formData); +</pre> + +<div class="note"><strong>Remarque :</strong> les champs "userfile" et "webmasterfile" contiennent tous les deux un fichier. Le nombre assigné au champ "accountnum" est immédiatement converti en une chaîne de caractères par la méthode <a href="/en/DOM/XMLHttpRequest/FormData#append()" title="en/XMLHttpRequest/FormData#append()"><code>FormData.append()</code></a> (la valeur du champ peut être soit un {{ domxref("Blob") }}, soit un {{ domxref("File") }}, ou encore une chaîne de caractères : <strong>si la valeur n'est ni un objet Blob ni un objet File, la valeur est convertie en une chaîne de caractères</strong>).</div> + +<p>Cet exemple crée une instance de <code>FormData</code> contenant des valeurs pour les champs nommés "username", "accountnum", "userfile" et "webmasterfile", puis utilise la méthode <a href="/en/DOM/XMLHttpRequest#send()" title="en/XMLHttpRequest#send()"><code>send()</code></a> de <code>XMLHttpRequest</code> pour envoyer les données du formulaire. Le champ "webmasterfile" est un <a href="/en/DOM/Blob" title="en/DOM/Blob"><code>Blob</code></a>. Un objet <a href="/en/DOM/Blob" title="en/DOM/Blob"><code>Blob</code></a> représente un pseudo-objet fichier de données brutes et immuables. Les Blobs représentent des données qui ne sont pas forcément dans un format natif de JavaScript. L'interface {{ domxref("File") }} est basée sur le <a href="/en/DOM/Blob" title="en/DOM/Blob"><code>Blob</code></a>, héritant des fonctionnalités du blob et l'étendant afin de supporter les fichiers système de l'utilisateur. Afin de construire un <a href="/en/DOM/Blob" title="en/DOM/Blob"><code>Blob</code></a>, vous pouvez invoquer le <a href="/en/DOM/Blob#Constructor" title="en/DOM/Blob#Constructor"><code>constructeur Blob</code></a>.</p> + +<h2 id="Récupérer_un_objet_FormData_à_partir_d'un_formulaire">Récupérer un objet <code>FormData</code> à partir d'un formulaire</h2> + +<p>Pour construire un objet <code>FormData</code> qui contient les données d'un {{ HTMLElement("form") }} existant, il suffit de spécifier cet élément formulaire lors de la création de l'objet <code>FormData</code> :</p> + +<pre class="brush: js">var formData = new FormData(someFormElement); +</pre> + +<p>Par exemple :</p> + +<pre class="brush: js">var formElement = document.getElementById("myFormElement"); +var request = new XMLHttpRequest(); +request.open("POST", "submitform.php"); +request.send(new FormData(formElement)); +</pre> + +<p>Vous pouvez également ajouter des données additionnelles à l'objet <code>FormData</code> après l'avoir extrait d'un formulaire et avant son envoi, comme ceci :</p> + +<pre class="brush: js">var formElement = document.getElementById("myFormElement"); +formData = new FormData(formElement); +formData.append("serialnumber", serialNumber++); +request.send(formData);</pre> + +<p>Cela vous permet de compléter les données du formulaire avant de les envoyer, en incluant des informations additionnelles qui ne sont pas nécessairement accessibles à l'utilisateur dans le formulaire.</p> + +<h2 id="Envoyer_des_fichiers_avec_un_objet_FormData">Envoyer des fichiers avec un objet <code>FormData</code></h2> + +<p>Vous pouvez aussi envoyer des fichiers en utilisant <code>FormData</code>. Il suffit d'inclure un élément {{ HTMLElement("input") }} de type "file" :</p> + +<pre class="brush: html"><form enctype="multipart/form-data" method="post" name="fileinfo"> + <label>Your email address:</label> + <input type="email" autocomplete="on" autofocus name="userid" placeholder="email" required size="32" maxlength="64" /><br /> + <label>Custom file label:</label> + <input type="text" name="filelabel" size="12" maxlength="32" /><br /> + <label>File to stash:</label> + <input type="file" name="file" required /> + <input type="submit" value="Stash the file!" /> +</form> +<div id="output"></div> +</pre> + +<p>Vous pouvez ensuite l'envoyer en utilisant un code semblable à celui-ci :</p> + +<pre class="brush: js">var form = document.forms.namedItem("fileinfo"); +form.addEventListener('submit', function(ev) { + + var + oOutput = document.getElementById("output"), + oData = new FormData(document.forms.namedItem("fileinfo")); + + oData.append("CustomField", "This is some extra data"); + + var oReq = new XMLHttpRequest(); + oReq.open("POST", "stash.php", true); + oReq.onload = function(oEvent) { + if (oReq.status == 200) { + oOutput.innerHTML = "Uploaded!"; + } else { + oOutput.innerHTML = "Error " + oReq.status + " occurred uploading your file.<br \/>"; + } + }; + + oReq.send(oData); + ev.preventDefault(); +}, false); +</pre> + +<div class="note"> +<p><strong>Remarque </strong>: si vous passez une référence au formulaire, la méthode spécifiée dans le formulaire sera utilisée en remplacement de celle précisée dans l'appel à open().</p> +</div> + +<div class="note"> +<p><strong>Remarque </strong>: Cet exemple redirige les données en sortie vers un script PHP sur le serveur, et gère les erreurs HTTP, quoique d'une manière peu élégante.</p> +</div> + +<p>Vous pouvez aussi ajouter un {{ domxref("File") }} ou un {{ domxref("Blob") }} directement à l'objet {{ domxref("XMLHttpRequest/FormData", "FormData") }}, comme ceci :</p> + +<pre class="brush: js">data.append("myfile", myBlob, "filename.txt"); +</pre> + +<p>Lorsque la méthode <code>append</code> est utilisée, il est possible de renseigner le troisième paramètre optionnel pour passer un nom de fichier à l'en-tête <code>Content-Disposition</code> qui est envoyée au serveur. Si aucun nom de fichier n'est spécifié (ou si le paramètre n'est pas supporté,) le nom "blob" est utilisé.</p> + +<p>Vous pouvez aussi utiliser <code>FormData</code> avec jQuery si vous configurez les bonnes options :</p> + +<pre class="brush: js">var fd = new FormData(document.getElementById("fileinfo")); +fd.append("CustomField", "This is some extra data"); +$.ajax({ + url: "stash.php", + type: "POST", + data: fd, + processData: false, // indique à jQuery de ne pas traiter les données + contentType: false // indique à jQuery de ne pas configurer le contentType +}); +</pre> + +<h2 id="Soumettre_des_formulaires_et_téléverser_des_fichiers_via_AJAX_sans_objets_FormData">Soumettre des formulaires et téléverser des fichiers via AJAX <em>sans</em> <code>objets FormData</code></h2> + +<p>Si vous souhaitez savoir comment sérialiser et soumettre via <a href="/en-US/docs/AJAX" title="/en-US/docs/AJAX">AJAX</a> un formulaire<em> sans</em> utiliser d'objets FormData, veuillez consulter <a href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Submitting_forms_and_uploading_files" title="/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest#Submitting_forms_and_uploading_files">ce paragraphe</a>.</p> + +<h2 id="Voir_aussi">Voir aussi</h2> + +<ul> + <li><a href="/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest" title="/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest">Using XMLHttpRequest</a></li> + <li><a href="/en-US/docs/DOM/HTMLFormElement" title="/en-US/docs/DOM/HTMLFormElement"><code>HTMLFormElement</code></a></li> + <li><a href="/en-US/docs/DOM/Blob" title="/en-US/docs/DOM/Blob"><code>Blob</code></a></li> + <li><a href="/en-US/docs/JavaScript/Typed_arrays" title="/en-US/docs/JavaScript/Typed_arrays">Typed Arrays</a></li> +</ul> |