From 39f2114f9797eb51994966c6bb8ff1814c9a4da8 Mon Sep 17 00:00:00 2001 From: Florian Merz Date: Thu, 11 Feb 2021 12:36:08 +0100 Subject: unslug fr: move --- .../creating_and_triggering_events/index.html | 96 ----- .../guide/dom/events/evenement_medias/index.html | 266 -------------- files/fr/web/guide/dom/events/index.html | 18 - .../index.html" | 76 ---- .../index.html" | 64 ---- .../web/guide/dom/events/touch_events/index.html | 245 ------------- files/fr/web/guide/dom/index.html | 30 -- .../example/index.html | 392 --------------------- .../manipuler_historique_du_navigateur/index.html | 245 ------------- .../guide/dom/using_full_screen_mode/index.html | 301 ---------------- 10 files changed, 1733 deletions(-) delete mode 100644 files/fr/web/guide/dom/events/creating_and_triggering_events/index.html delete mode 100644 files/fr/web/guide/dom/events/evenement_medias/index.html delete mode 100644 files/fr/web/guide/dom/events/index.html delete mode 100644 "files/fr/web/guide/dom/events/les_donn\303\251es_d_orientation_et_de_mouvement_expliqu\303\251es/index.html" delete mode 100644 "files/fr/web/guide/dom/events/touch_events/g\303\251rer_\303\240_la_fois_\303\251v\303\251nement_tactile_et_\303\251v\303\251nement_de_la_souris/index.html" delete mode 100644 files/fr/web/guide/dom/events/touch_events/index.html delete mode 100644 files/fr/web/guide/dom/index.html delete mode 100644 files/fr/web/guide/dom/manipuler_historique_du_navigateur/example/index.html delete mode 100644 files/fr/web/guide/dom/manipuler_historique_du_navigateur/index.html delete mode 100644 files/fr/web/guide/dom/using_full_screen_mode/index.html (limited to 'files/fr/web/guide/dom') 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 deleted file mode 100644 index 686d138cfc..0000000000 --- a/files/fr/web/guide/dom/events/creating_and_triggering_events/index.html +++ /dev/null @@ -1,96 +0,0 @@ ---- -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 ---- -

Cet article montre comment créer et distribuer des événements DOM. De tels événements sont généralement appelés événements synthétiques afin de les distinguer des événements levés par le navigateur lui-même.

- -

Création d'événements personnalisés

- -

Les événements peuvent être créés avec le constructeur Event de cette manière :

- -
var event = new Event('build');
-
-//Ecouter l'événement.
-elem.addEventListener('build', function (e) { ... }, false);
-
-//distribuer l'événement.
-elem.dispatchEvent(event);
- -

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 l'ancienne approche ci-dessous.

- -

Ajout de données personnalisée - CustomEvent ()

- -

Pour ajouter d'autres données à l'objet événement, il existe l'interface CustomEvent. Dans cette interface, la propriété detail peut être utilisée pour transmettre des données personnalisées. Par exemple, l'événement peut être créé de la manière suivante :

- -
var event = new CustomEvent('build', { 'detail': elem.dataset.time });
- -

Cela permet à la fonction qui capture l'événement (la fonction de rappel) d'accéder aux données supplémentaires :

- -
function eventHandler(e) {
-  log('The time is: ' + e.detail);
-}
-
- -

L'ancienne approche

- -

L'ancienne manière de créer des événements utilise des API inspirées par Java. Le code suivant en montre un exemple :

- -
// 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);
-
-
- -

Le déclenchement d'événements intégrés

- -

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. Voir l'exemple en action.

- -
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");
-  }
-}
- -

Compatibilité des navigateurs

- - - -

{{Compat("api.Event.Event")}}

- -

Voir aussi

- - diff --git a/files/fr/web/guide/dom/events/evenement_medias/index.html b/files/fr/web/guide/dom/events/evenement_medias/index.html deleted file mode 100644 index c34862e7db..0000000000 --- a/files/fr/web/guide/dom/events/evenement_medias/index.html +++ /dev/null @@ -1,266 +0,0 @@ ---- -title: Evénements des Médias -slug: Web/Guide/DOM/Events/evenement_medias -tags: - - Media -translation_of: Web/Guide/Events/Media_events ---- -

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.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nom de l'événementDescription
abortEnvoyé 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é.
{{event("canplay")}}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 HAVE_ENOUGH_DATA de la propriété readyState.
{{event("canplaythrough")}}Envoyé quand l'état de disponibilité change pour CAN_PLAY_THROUGH, 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. Note: Changer manuellement la valeur currentTime peut éventuellement déclencher cet évenement dans firefox. Les autres navigateurs peuvent ne pas envoyer cet événement.
{{event("durationchange")}}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.
{{event("emptied")}}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 load() a été appellée pour le re-télécharger.
encrypted {{experimental_inline}}L'agent utilisateur a trouvé des données d'initialisation d'acquisition de licence dans les données du média.
endedEnvoyé quand la lecture du média est terminée.
errorEnvoyé quand une erreur intervient. L'attribut error de l'élément contient plus d'informations. Voir Error handling pour plus de détails.
interruptbeginEnvoyé 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 Using the AudioChannels API pour plus de détails.
interruptendEnvoyé 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 Using the AudioChannels API pour plus de détails.
{{event("loadeddata")}}La première frame du media a fini de se télécharger.
{{event("loadedmetadata")}}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.
{{event("loadstart")}}Envoyé lorsque le téléchargement du média commence.
mozaudioavailableEnvoyé 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.
{{event("pause")}}Envoyé quand la lecture du média est mise en pause.
{{event("play")}}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.
{{event("playing")}}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).
{{event("progress")}}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é buffered de l'élément.
{{event("ratechange")}}Envoyé lorsque la vitesse de lecture du média change.
{{event("seeked")}}Envoyé lorsqu'une opération de déplacement dans le média est terminée.
{{event("seeking")}}Envoyé lorsqu'une opération de déplacement dans le média commence.
{{event("stalled")}}Envoyé lorsque l'agent utilisateur essaye de télécharger des données du média mais que celle-ci sont indisponibles.
{{event("suspend")}}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.
{{event("timeupdate")}}La position de la tête de lecture dans le média indiquée par l'attribut currentTime de l'élément a changée.
{{event("volumechange")}}Envoyé lorsque le volume sonore du lecteur ou que l'attribut muted de l'élément changent.
{{event("waiting")}}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).
- -

Vous pouvez facilement écouter ces événements en utilisant du code ci-dessous :

- -
var v = document.getElementsByTagName("video")[0];
-v.addEventListener("seeked", function() { v.play(); }, true);
-v.currentTime = 10.0;
-
- -

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 seeked est envoyé. Cet écouteur appèle la méthode play() de l'élément, qui démarre la lecture.

- -

Ensuite, en ligne 3, l'exemple définit la propriété currentTime 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 seeking quand elle commence, puis un évenement seeked quand elle se termine.

- -

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.

- -

Compatibilité des navigateurs

- -

{{ CompatibilityTable() }}

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FonctionnalitéChromeFirefox (Gecko)Internet ExplorerOperaSafari
Support basique{{ CompatUnknown() }}{{ CompatGeckoDesktop("1.9.1") }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}
encrypted{{CompatChrome(42.0)}} -

 

-
{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}
load{{ CompatUnknown() }}{{CompatNo}} [1]{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}
mozaudioavailable {{ non-standard_inline() }}{{ CompatNo() }}{{ CompatGeckoDesktop("2.0") }}{{ CompatNo() }}{{ CompatNo() }}{{ CompatNo() }}
suspend{{ CompatUnknown() }}{{ CompatGeckoDesktop("1.9.2") }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FonctionnalitéAndroidAndroid WebviewFirefox Mobile (Gecko)IE MobileOpera MobileSafari MobileChrome for Android
Support basique{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}
encrypted{{ CompatNo }}{{CompatChrome(43.0)}}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{CompatChrome(42.0)}} -

 

-
load{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}
mozaudioavailable {{ non-standard_inline() }}{{ CompatNo() }}{{ CompatUnknown() }}{{ CompatGeckoMobile("2.0") }}{{ CompatNo() }}{{ CompatNo() }}{{ CompatNo() }}{{ CompatUnknown() }}
suspend{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}
-
- -

[1] Supprimé dans Gecko 1.9.2.

diff --git a/files/fr/web/guide/dom/events/index.html b/files/fr/web/guide/dom/events/index.html deleted file mode 100644 index 475aa10cde..0000000000 --- a/files/fr/web/guide/dom/events/index.html +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Event developer guide -slug: Web/Guide/DOM/Events -tags: - - DOM - - Event - - Guide - - TopicStub - - events -translation_of: Web/Guide/Events ---- -

{{draft()}}

- -

Tout ce que vous devez savoir sur les événements sera présenté ici. Nous travaillons sur le nettoyage ici maintenant.

- -

Docs

- -

{{LandingPageListSubpages}}

diff --git "a/files/fr/web/guide/dom/events/les_donn\303\251es_d_orientation_et_de_mouvement_expliqu\303\251es/index.html" "b/files/fr/web/guide/dom/events/les_donn\303\251es_d_orientation_et_de_mouvement_expliqu\303\251es/index.html" deleted file mode 100644 index f7f7f0c204..0000000000 --- "a/files/fr/web/guide/dom/events/les_donn\303\251es_d_orientation_et_de_mouvement_expliqu\303\251es/index.html" +++ /dev/null @@ -1,76 +0,0 @@ ---- -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 ---- -

{{ Draft() }}

- -

Résumé

- -

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.

- -
-

Attention : Actuellement, Firefox et Chrome ne gèrent pas ces  coordonnées de la même manière. Prenez-y garde en les utilisant.

-
- -

À propos des cadres de coordonnées

- -

Un cadre de coordonnées 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:

- -

Le cadre de coordonnées de la Terre

- -

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.

- - - -

Le cadre de coordonnées de l'appareil

- -

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.

- -

axes.png

- - - -
Note : 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 orientationchange.
- -

À propos de la rotation

- -

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.

- -

Alpha

- -

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 :

- -

alpha.png

- -

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.

- -

Beta

- -

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 beta :

- -

beta.png

- -

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.

- -

Gamma

- -

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 gamma :

- -

gamma.png

- -

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.

diff --git "a/files/fr/web/guide/dom/events/touch_events/g\303\251rer_\303\240_la_fois_\303\251v\303\251nement_tactile_et_\303\251v\303\251nement_de_la_souris/index.html" "b/files/fr/web/guide/dom/events/touch_events/g\303\251rer_\303\240_la_fois_\303\251v\303\251nement_tactile_et_\303\251v\303\251nement_de_la_souris/index.html" deleted file mode 100644 index 97174a4763..0000000000 --- "a/files/fr/web/guide/dom/events/touch_events/g\303\251rer_\303\240_la_fois_\303\251v\303\251nement_tactile_et_\303\251v\303\251nement_de_la_souris/index.html" +++ /dev/null @@ -1,64 +0,0 @@ ---- -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 ---- -

{{DefaultAPISidebar("Touch Events")}}

- -

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 à émuler les événements de la souris, donc le contenu qui se veut fonctionner uniquement à la souris fonctionnera toujours tel quel sans modification directe.

- -

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.

- -

Déclenchement de l'événement

- -

La norme des événements tactiles définit quelques exigences envers les navigateurs concernant l'interaction tactile et souris (voir la section Interaction with Mouse Events and click pour plus de détails), noter que 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. Cette section décrit les exigences pouvant affecter une application.

- -

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 doit 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é.

- -

Voici un extrait de code du gestionnaire de l'événement {{event("touchmove")}} qui appelle preventDefault().

- -
// touchmove handler
-function process_touchmove(ev) {
-  // Call preventDefault() to prevent any further handling
-  ev.preventDefault();
-}
-
- -

Ordre des événements

- -

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 représentatif: pour une entrée :

- - - -

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 :

- - - -

Community

- - - - - - diff --git a/files/fr/web/guide/dom/events/touch_events/index.html b/files/fr/web/guide/dom/events/touch_events/index.html deleted file mode 100644 index 7f3cbae7b5..0000000000 --- a/files/fr/web/guide/dom/events/touch_events/index.html +++ /dev/null @@ -1,245 +0,0 @@ ---- -title: Événements tactiles / Touch events -slug: Web/Guide/DOM/Events/Touch_events -tags: - - Tactile - - touch -translation_of: Web/API/Touch_events ---- -

{{DefaultAPISidebar("Touch Events")}}

- -

Afin de fournir un support de qualité pour les interfaces tactiles, les événements tactiles (touch events) permettent d'interpréter les interactions tactiles (sur les écrans ou trackpads).

- -

Définitions

- -
-
Surface
-
La surface tactile. Cela peut être un écran ou un trackpad.
-
- -
-
Point de toucher (Touch point)
-
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).
-
- -

Interfaces

- -
-
{{ domxref("TouchEvent") }}
-
Représente l'événement qui se produit quand l'action de toucher change.
-
{{ domxref("Touch") }}
-
Représente un point unique de contact entre l'utilisateur et la surface tactile.
-
{{ domxref("TouchList") }}
-
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.
-
{{ domxref("DocumentTouch") }}
-
Contient des méthodes permettant de créer les objets  {{ domxref("Touch") }} et {{ domxref("TouchList") }}.
-
- -

Exemple

- -

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.

- -
Note : 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...).
- -

Initialiser les gestionnaires d'événements

- -

Quand la page charge, la fonction startup() décrite ci-dessous est appelée par l'attribut onload de l'élément {{ HTMLElement("body") }}.

- -
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);
-}
-
- -

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.

- -

Gérer les nouveaux touchers

- -

Quand un événement touchstart se produit, cela indique qu'un nouveau toucher s'est produit. La fonction handleStart() est alors appelée.

- -
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);
-  }
-}
-
- -

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.

- -

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).

- -

Dessiner avec les déplacements

- -

Chaque fois que le(s) doigt(s) bouge(nt), un événement touchmove est déclenché, ce qui provoque l'appel de la fonction handleMove() 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.

- -
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
-  }
-}
-
- -

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.

- -

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.

- -

Une fois le segment dessiné, on appelle Array.splice() pour remplacer les informations précédentes sur les points de toucher par les informations courantes contenues dans le tableau ongoingTouches.

- -

Gérer la fin d'un toucher

- -

Lorsqu'un utilisateur enlève son doigt de la surface, un événement touchend est envoyé. De la même manière, un événement touchleave sera envoyé si le doigt sort du canvas. Ici, les deux événements sont gérés en commun avec la fonction handleEnd() 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.

- -
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
-  }
-}
-
- -

Cette fonction ressemble beaucoup à la précédente sauf qu'ici en appelant Array.splice(), on retire simplement l'ancien point sans ajouter un point mis à jour. On arrête donc de « suivre » ce point.

- -

Gérer l'annulation d'un toucher

- -

Si le doigt de l'utilisateur se balade dans l'interface du navigateur ou si un toucher doit être annulé, l'événement touchcancel est envoyé et on appelle alors la fonction handleCancel().

- -
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
-  }
-}
-
- -

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.

- -

Fonctions auxiliaires

- -

Cet exemple utilise deux fonctions auxiliaires qu'il est conseillé de lire rapidement afin de mieux comprendre le reste du code.

- -

Sélectionner une couleur pour chaque toucher

- -

Afin que chaque contact soit différent, on utilisera la fonction colorForTouch() 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.

- -
function colorForTouch(touch) {
-  var id = touch.identifier;
-  id = id.toString(16); // creer un nombre hexadécimal
-  return "#" + id + id + id;
-}
-
- -

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".

- -

Retrouver un toucher en cours

- -

La fonction ongoingTouchIndexById() analyse le tableau ongoingTouches pour trouver le toucher correspondant à l'identifiant donné. Elle retourne alors l'indice du toucher dans le tableau.

- -
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é
-}
-
- -

Voir l'exemple sur une page

- -

Astuces supplémentaires

- -

Cette section fournit quelques astuces supplémentaires pour gérer les événements tactiles au sein de votre application web.

- -

Gérer les clics

- -

Étant donné que l'appel de la méthode preventDefault() sur l'événement  touchstart ou le premier événement touchmove de la série empêche la saisie d'événements en provenance de la souris, on appelle souvent  preventDefault() sur touchmove plutôt que sur touchstart. 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.)

- -
function onTouch(evt) {
-  evt.preventDefault();
-  if (evt.touches.length > 1 || (evt.type == "touchend" && evt.touches.length > 0))
-    return;
-
-  var newEvt = document.createEvent("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.initMouseEvent(type, true, true, event.originalTarget.ownerDocument.defaultView, 0,
-    touch.screenX, touch.screenY, touch.clientX, touch.clientY,
-    evt.ctrlKey, evt.altKey, evt.shirtKey, evt.metaKey, 0, null);
-  event.originalTarget.dispatchEvent(newEvt);
-}
-
- -

Appeler preventDefault() uniquement pour un deuxième toucher

- -

Pour éviter que des événements de zoom (comme pinchZoom) ne se produisent sur la page, il est possible d'appeler la méthode preventDefault() 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 (viewport) pour éviter un zoom quelconque.

- -
-
- -

Compatibilité des navigateurs

- -

{{Compat("api.Touch")}}

- -
 
- -

Notes relatives à Gecko

- -

Le paramètre dom.w3c_touch_events.enabled 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.

- -
-

{{ gecko_callout_heading("12.0") }}

- -

Avant Gecko 12.0 {{ geckoRelease("12.0") }}, Gecko ne supportait pas les contacts multiples simultanés. Seul un toucher à la fois était supporté.

-
- -
Note : Avant Gecko 6.0 {{ geckoRelease("6.0") }}, Gecko permettait d'utiliser une API propriétaire pour les événements tactile. Cette API est maintenant dépréciée, celle-ci doit être utilisée à la place.
diff --git a/files/fr/web/guide/dom/index.html b/files/fr/web/guide/dom/index.html deleted file mode 100644 index ad672dee28..0000000000 --- a/files/fr/web/guide/dom/index.html +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Guides DOM pour développeurs -slug: Web/Guide/DOM -tags: - - API - - DOM - - Guide - - TopicStub -translation_of: Web/API/Document_Object_Model -translation_of_original: Web/Guide/API/DOM ---- -

{{draft}}

- -

Le Document Object Model est une API pour les documents HTML et XML. 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.

- -

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 objects (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.

- -

Le DOM est le plus souvent utilisé en conjonction avec JavaScript. 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. Bien que nous nous concentrions sur JavaScript tout au long de ce site, les implémentations du DOM peuvent être construites pour n'importe quel langage.

- -

Le World Wide Web Consortium établit une norme pour le DOM, appelée W3C DOM. Il devrait, maintenant que les navigateurs les plus importants l'implémentent correctement, activer de puissantes applications multi-navigateurs.

- -

Pourquoi le DOM est-il important?

- -

"HTML dynamique" (DHTML) 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 FAQ du W3C). 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.

- -

Encore plus important est le fait que l'interface utilisateur de Mozilla (également Firefox et Thunderbird) est construite en utilisant XUL, en utilisant le DOM pour manipuler sa propre interface utilisateur.

- -

En savoir plus sur le DOM

- -

{{LandingPageListSubpages}}

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 deleted file mode 100644 index f19782d753..0000000000 --- a/files/fr/web/guide/dom/manipuler_historique_du_navigateur/example/index.html +++ /dev/null @@ -1,392 +0,0 @@ ---- -title: Exemple de navigation en Ajax -slug: Web/Guide/DOM/Manipuler_historique_du_navigateur/Example -translation_of: Web/API/History_API/Example ---- -

Voici un exemple de site web AJAX composé uniquement de trois pages (page_un.phppage_deux.php et page_trois.php). Pour tester cet exemple, merci de créer les fichiers suivants :

-

page_un.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>";
-    }
-?>
-
-
-

page_deux.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>";
-    }
-?>
-
-
-

page_trois.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>";
-    }
-?>
-
-
-

css/style.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;
-}
-
-

include/after_content.php:

-
<p>Ceci est le pied-de-page. Il est commun à toutes les pages ajax.</p>
-
-

include/before_content.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>
-
-
-

include/header.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" />
-
-

js/ajax_nav.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;
-
-})();
-
-
-
- Note: const (instruction de constante) ne fait pas partie de ECMAScript 5. Il est supporté dans Firefox et Chrome (V8) et partiellement supporté dans Opera 9+ et Safari. Il n'est pas supporté dans Internet Explorer 6-9, ou dans la version de prévisualisation de Internet Explorer 10const sera défini par ECMAScript 6, mais avec une sémantique différente. Proches des variables déclarées avec l'instruction let, les constantes déclarées avec const seront limitées en portée. 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 à const par des instructions var.
-

Pour plus d'informations, voyez : Manipuler l'historique du navigateur.

-

Lire également

- 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 deleted file mode 100644 index 5e199dd521..0000000000 --- a/files/fr/web/guide/dom/manipuler_historique_du_navigateur/index.html +++ /dev/null @@ -1,245 +0,0 @@ ---- -title: Manipuler l'historique du navigateur -slug: Web/Guide/DOM/Manipuler_historique_du_navigateur -tags: - - API - - DOM - - Historique -translation_of: Web/API/History_API ---- -

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.

- -

Se déplacer dans l'historique

- -

Avancer ou reculer dans l'historique de l'utilisateur est possible en utilisant les méthodes back(), forward() et go().

- -

Avancer et reculer

- -

Pour reculer dans l'historique, il vous suffit de faire :

- -
window.history.back();
-
- -

Cela agira exactement comme si l'utilisateur cliquait sur le bouton Retour de la barre d'outils de son navigateur.

- -

De la même manière, il est possible d'avancer (comme si l'utilisateur cliquait sur le bouton Avancer) :

- -
window.history.forward();
-
- -

Se déplacer à un élément précis de l'historique

- -

Vous pouvez utiliser la méthode go() 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).

- -

Pour reculer d'une page (l'équivalent d'un appel à back()):

- -
window.history.go(-1);
-
- -

Pour avancer d'une page, comme en appelant forward():

- -
window.history.go(1);
-
- -

De la même manière, vous pouvez avancer de 2 pages en passant la valeur 2, et ainsi de suite.

- -

Vous pouvez déterminer le nombre de pages de l'historique en accédant à la valeur de la propriété length (longeur) :

- -
var numberOfEntries = window.history.length;
-
- -
Note: Internet Explorer supporte le passage d'une URL sous forme de chaîne de caractères comme paramètre de la méthode go(); ce comportement est non standard et non supporté par Gecko.
- -

Ajouter et modifier des entrées de l'historique

- -

{{ gecko_minversion_header("2") }}

- -

HTML5 a introduit les méthodes history.pushState() et history.replaceState(), qui permettent, respectivement, d'ajouter et de modifier des entrées de l'historique. Ces méthodes fonctionnent conjointement avec l'événement onpopstate.

- -

L'utilisation de history.pushState() change le référent créé habituellement dans l'en-tête HTTP pour les objets XMLHttpRequest, chaque fois que son état a été changé. Le référent sera l'URL de la page dont l'objet window est this au moment de la création de l'objet XMLHttpRequest.

- -

Exemple de la méthode pushState()

- -

Supposons que http://mozilla.org/foo.html exécute la séquence JavaScript suivante :

- -
var stateObj = { foo: "bar" };
-history.pushState(stateObj, "page 2", "bar.html");
-
- -

Cela va provoquer l'apparition dans la barre de navigation de http://mozilla.org/bar.html, mais ne provoquera pas le chargement effectif de bar.html ni même le test d'existence de bar.html.

- -

Supposons à présent que l'utilisateur accède à la page http://google.com, puis clique sur l'icône "Recul". La barre de navigation va alors afficher http://mozilla.org/bar.html, et si vous lisez l'history.state, vous obtiendrez le stateObj.  L'événement popstate ne sera pas lancé car la page a été rechargée. La page elle-même ressemblera à bar.html.

- -

Si on clique à nouveau sur Recul, l'URL de la barre de navigation va se changer en http://mozilla.org/foo.html et le document va recevoir un autre événement popstate, 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 popstate.

- -

La méthode pushState()

- -

La méthode pushState() 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 :

- - - -
Note : 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 "structured clone algorithm" 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.
- -

On peut assimiler l'appel à pushState() à l'affectation window.location = "#foo", 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 pushState() a quelques avantages :

- - - -

Notez que pushState() n'entraîne jamais le déclenchement d'un événement hashchange, même si la nouvelle URL diffère de l'ancienne seulement par son hash.

- -

Dans un document XUL elle crée l'élément XUL spécifié.

- -

Dans d'autres documents, elle crée un élément avec l'URI d'espace de nom null

- -

La méthode replaceState()

- -

history.replaceState() fonctionne exactement comme history.pushState() hormis le fait que replaceState() 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.

- -

replaceState() 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.

- -
Note : 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 "structured clone algorithm" 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.
- -

Exemple de la méthode replaceState()

- -

Supposons que http://mozilla.org/foo.html exécute le code JavaScript suivant :

- -
var stateObj = { foo: "bar" };
-history.pushState(stateObj, "page 2", "bar.html");
- -

L'explication des deux lignes ci-dessus peut être trouvée dans la section "Exemple de la méthode pushState()". Supposons ensuite que http://mozilla.org/bar.html exécute le code JavaScript suivant :

- -
history.replaceState(stateObj, "page 3", "bar2.html");
- -

Cela entraînera l'affichage de la barre d'URL http://mozilla.org/bar2.html, mais le navigateur ne chargera pas bar2.html ou même vérifiera que bar2.html existe.

- -

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.

- -

L'événement popstate

- -

Un événement popstate 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 à replaceState, la propriété state de l'événement popstate contient une copie de l'objet état  de l'entrée de l'historique.

- -

Voir {{ domxref("window.onpopstate") }} pour un exemple d'utilisation.

- -

Lire l'état courant

- -

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  pushState() ou replaceState()) et qu'ensuite l'utilisateur redémarre le navigateur.  Quand votre page sera rechargée, elle recevra l'événement  onload , mais pas l'événement popstate.  Néanmoins, si vous lisez la propriété history.state, vous récupèrerez l'objet état que vous auriez obtenu si un événement popstate avait été déclenché.

- -

Vous pouvez lire l'état de l'entrée courante de l'historique sans devoir attendre un événement popstate en utilisant la propriété history.state comme ceci :

- -
var currentState = history.state;
-
- -

Exemples

- -

Pour un exemple comple de site web AJAX, vous pouvez voir : Exemple de navigation en Ajax.

- -

Spécifications

- - - - - - - - - - - - - - - - - - - -
SpécificationStatutCommentaire
{{SpecName('HTML WHATWG', "browsers.html#history", "History")}}{{Spec2('HTML WHATWG')}}Pas de changement de {{SpecName("HTML5 W3C")}}.
{{SpecName('HTML5 W3C', "browsers.html#history", "History")}}{{Spec2('HTML5 W3C')}}Définition initiale.
- -

Compatibilité des navigateurs

- -

{{ CompatibilityTable() }}

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
FonctionnalitéChromeFirefox (Gecko)Internet ExplorerOperaSafari
replaceState, pushState5{{ CompatGeckoDesktop("2.0") }}1011.505.0
history.state18{{ CompatGeckoDesktop("2.0") }}1011.50{{ CompatNo() }}
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
FonctionnalitéAndroidFirefox Mobile (Gecko)IE MobileOpera MobileSafari Mobile
replaceState, pushState{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}
history.state{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}
-
- -

Vous pouvez utiliser History.js pour contourner les problèmes de compatibilité entre navigateurs.

- -

Voir aussi

- - 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 deleted file mode 100644 index 76144c64f2..0000000000 --- a/files/fr/web/guide/dom/using_full_screen_mode/index.html +++ /dev/null @@ -1,301 +0,0 @@ ---- -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 ---- -

{{DefaultAPISidebar("Fullscreen API")}}

- -

L'API Fullscreen (plein écran) fournit un moyen simple de présenter du contenu web en utilisant l'ensemble de l'écran de l'utilisateur. 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.

- -
Note : Pour le moment, tous les navigateurs n'utilisent pas la version non préfixée de cet API. Consultez le tableau récapitulant les préfixes et les différences de noms entre eux (vous pouvez également utiliser Fscreen pour l'accès du fournisseur à l'API).
- -

Activation du mode plein écran

- -

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()") }} .

- -

Prenons cet élément {{ HTMLElement("video") }} :

- -
<video controls id="myvideo">
-  <source src="somevideo.webm"></source>
-  <source src="somevideo.mp4"></source>
-</video>
-
- -

Nous pouvons mettre cet élément video en plein écran avec un script de cette façon :

- -
var elem = document.getElementById("myvideo");
-if (elem.requestFullscreen) {
-  elem.requestFullscreen();
-}
- -

Différences de présentation

- -

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 : "width: 100%; height: 100%". 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 "width: 100%; height: 100%;" à l'élément :

- -
#myvideo:-webkit-full-screen  {
-  width: 100%;
-  height: 100%;
-}
-
- -

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.

- -

Notification

- -

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.

- -

Lorsqu'une demande de plein écran échoue

- -

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  mozfullscreenerror . 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. Dans Chrome et les versions plus récentes d'Opera, aucun avertissement de ce type n'est généré.

- -
-

Note : Les requêtes de Fullscreen doivent être appelées depuis un gestionnaire d'évènements ou sinon, elles seront refusées.

-
- -

Sortie du mode plein écran

- -

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()")}} .

- -

Autres informations

- -

Le {{ domxref("document") }} fournit des informations supplémentaires pouvant être utiles lorsque vous développez des applications web en plein écran :

- -
-
{{ domxref("document.fullscreenElement", "fullscreenElement") }}
-
L'attribut fullscreenElement 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.
-
{{ domxref("document.fullscreenEnabled", "fullscreenEnabled") }}
-
L'attribut fullscreenEnabled vous indique si le document est actuellement dans un état qui permettrait d'activer le mode plein écran ou non.
-
- -

Choses que vos utilisateurs doivent savoir

- -

Vous voulez faire savoir à vos utilisateurs qu'il peuvent utiliser la touche ECHAP  (ou  F11) pour sortir du mode plein écran.

- -

En même temps, naviguer sur une autre page, changer d'onglet, ou changer d'application (en utilisant, par exemple, Alt-Tab ) pendant le mode plein écran, implique la sortie du mode plein écran de toute façon.

- -

Exemple

- -

Dans cet exemple, une vidéo est affichée dans une page web. Taper sur l'une des touches  Retour  ou Entrée, permet à l'utilisateur de passer d'une présentation dans une fenêtre à une présentation en mode plein écran de la vidéo.

- -

Voir l'exemple sur une page

- -

Action sur la touche Entrée

- -

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  Entrée .

- -
document.addEventListener("keydown", function(e) {
-  if (e.keyCode == 13) {
-    toggleFullScreen();
-  }
-}, false);
-
- -

Passer en mode plein écran

- -

Ce code est appelé lorsque l'utilisateur appuie sur la touche Entrée, comme vu plus haut.

- -
function toggleFullScreen() {
-  if (!document.fullscreenElement) {
-      document.documentElement.requestFullscreen();
-  } else {
-    if (document.exitFullscreen) {
-      document.exitFullscreen();
-    }
-  }
-}
- -

 Dans un premier temps, la valeur de l'attribut fullscreenElement est analysée dans le {{ domxref("document") }} (en contrôlant s'il est préfixé par moz-, ms- ou webkit-). 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()") }}.

- -

Si le mode plein écran est déjà activé (fullscreenElement est non nul), nous appelons  {{ domxref("document.exitFullscreen()") }}.

- -

Préfixes

- -

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 Fscreen) . Voici le tableau résumant les préfixes et les différences de noms entre eux :

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StandardBlink (Chrome & Opera)Gecko (Firefox)Internet Explorer 11EdgeSafari (WebKit)
{{domxref("Document.fullscreen")}}webkitIsFullScreenmozFullScreen-webkitIsFullScreenwebkitIsFullScreen
{{domxref("Document.fullscreenEnabled")}}webkitFullscreenEnabledmozFullScreenEnabledmsFullscreenEnabledwebkitFullscreenEnabledwebkitFullscreenEnabled
{{domxref("Document.fullscreenElement")}}webkitFullscreenElementmozFullScreenElementmsFullscreenElementwebkitFullscreenElementwebkitFullscreenElement
{{domxref("Document.onfullscreenchange")}}onwebkitfullscreenchangeonmozfullscreenchangeMSFullscreenChangeonwebkitfullscreenchangeonwebkitfullscreenchange
{{domxref("Document.onfullscreenerror")}}onwebkitfullscreenerroronmozfullscreenerrorMSFullscreenErroronwebkitfullscreenerroronwebkitfullscreenerror
{{domxref("Document.exitFullscreen()")}}webkitExitFullscreen()mozCancelFullScreen()msExitFullscreen()webkitExitFullscreen()webkitExitFullscreen()
{{domxref("Element.requestFullscreen()")}}webkitRequestFullscreen()mozRequestFullScreen()msRequestFullscreen()webkitRequestFullscreen()webkitRequestFullscreen()
- -

Spécifications

- - - - - - - - - - - - - - - - -
SpecificationStatutCommentaire
{{SpecName("Fullscreen")}}{{Spec2("Fullscreen")}}Définition initiale.
- -

Compatibilité des navigateurs

- -

Tous les navigateurs implémentent cette API. Néanmoins certains l'implémentent avec des préfixes avec des noms légèrement différents ; par exemple, au lieu de requestFullscreen (), il y a MozRequestFullScreen ().

- -

{{ CompatibilityTable() }} 

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FonctionnalitéChromeEdgeFirefox (Gecko)Internet ExplorerOperaSafari
Basic support15 {{ property_prefix("-webkit") }}{{CompatVersionUnknown}}{{ CompatGeckoDesktop("9.0") }} {{ property_prefix("-moz") }}
- {{CompatGeckoDesktop("47")}} (behind full-screen-api.unprefix.enabled)
11 {{ property_prefix("-ms") }}12.105.0 {{ property_prefix("-webkit") }}
fullscreenEnabled20 {{ property_prefix("-webkit") }}{{CompatVersionUnknown}}{{ CompatGeckoDesktop("10.0") }} {{ property_prefix("-moz") }}
- {{CompatGeckoDesktop("47")}} (behind full-screen-api.unprefix.enabled)
11 {{ property_prefix("-ms") }}12.105.1 {{ property_prefix("-webkit") }}
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FonctionnalitéAndroidChromeEdgeFirefox Mobile (Gecko)IE MobileOpera MobileSafari Mobile
Basic support{{ CompatUnknown() }}28 {{ property_prefix("-webkit") }}{{CompatVersionUnknown}}{{ CompatGeckoMobile("9.0") }}{{ property_prefix("-moz") }}
- {{CompatGeckoMobile("47")}} (behind full-screen-api.unprefix.enabled)
{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}
fullscreenEnabled{{ CompatUnknown() }}28 {{ property_prefix("-webkit") }}{{CompatVersionUnknown}}{{ CompatGeckoMobile("10.0") }} {{ property_prefix("moz") }}
- {{CompatGeckoMobile("47")}} (behind full-screen-api.unprefix.enabled)
{{ CompatUnknown() }}{{ CompatUnknown() }}{{ CompatUnknown() }}
-
-
- -

Voir aussi

- - -- cgit v1.2.3-54-g00ecf