Javascript

Mots-clefs

Les éléments de base du JS doivent vous êtes familiers; parmi eux: let const for...of... => ... async function* class

Events

Là encore, il existe énormément d'évènements en javascript et le MDN vous en donne la liste exhaustive , dont les plus intéressants/exotiques sont peut-être: ClipboardEvent CustomEvent DeviceLightEvent DevicemotionEvent KeyboardEvent MouseEvent MessageEvent NavigatorOnLine PageTransitionEvent PointerEvent DeviceProximityEvent UserProximityEvent WheelEvent .
Tâchez de bien comprendre chacun de ceux que vous utilisez: input et change n'ont pas la même signification!

Notez aussi qu'il existe plusieurs fonction utiles liées à ces events, comme preventDefault() stopPropagation() , lié à l'interface Event elle-même et dispatchEvent , liée à l'interface EventTarget (souvent, un noeud du DOM, mais pas uniquement).

L'Event "click" peut être triggé par un terminal tactile (touch), vocal, ou autre: ce n'est pas forcément un click souris, malgré son nom.

Il n'y a pas de moyen standard de connaître "l'élément d'origine de l'Event". Ce genre de besoin reflète d'ailleurs un mauvais usage des events: posez le listener sur l'objet "d'origine" que vous souhaitiez écouter, tout simplement!

Form submit Event et formaction

Si un script ajoute un listener submit sur un <form> et que ce formulaire a été soumis en utilisant un <input|button formaction=.../>, alors le listener n'a aucun moyen standard de connaître la vraie destination (action) du formulaire. Mieux vaut alors faire plusieurs form, ou poser un listener click sur ces input|button.

<form action="?action=original" method="POST"> <input type="text" name="x" value="123"/> <input type="submit" value="Go!"/> <input type="submit" formaction="?action=formaction" value="FormAction!"/> </form> <script> document.querySelector('form').addEventListener('submit', function (e) { // You cannot know the "formaction" from there! console.log(this, e, e.explicitOriginalTarget); }); </script>
Impossible de savoir, dans la callback du listener, si l'utilisateur a cliqué sur Go! ou sur FormAction!
document.querySelector('input[formaction]').addEventListener('click', function (e) { this.form.setAttribute('action', this.getAttribute('formaction')); });
La seule solution est de poser un listener sur chaque tag ayant un formaction, ou de faire plusieurs tags <form>.

Promise

Une Promise est simplement un objet javascript, créé instantanément, et qui sera "résolu" plus tard, quand une opération sera terminée. Quand cette "résolution" aura lieu, une callback sera appelée C'est donc une forme "d'asynchrone", raison pour laquelle elle rejoint le concept de async await .

Cette interface est très utilisée par les APIs natives du VanillaJS. Tâchez de comprendre son principe de fonctionnement avant de plonger dans ces autres APIs.

Web APIs et interfaces

Il existe un paquet d'APIs web et d'interfaces entre la page HTML (le DOM) et le code javascript. Je vous recommande donc d'en faire le tour, et de surtout maîtriser celle que vous utiliserez. Les plus utiles et remarquables sont sans doute: ChildNode CharacterData DOMClassList / DOMTokenList DOMException DOMPoint .

L'article du MDN sur le DOM liste aussi de nombreuses autres interfaces utiles.

API/interfaces notables

Voici quelques APIs (en vrac) dignes d'intérêt dans le cadre d'un jeu web.

Atomics : type de données pour le multi-thread

Audio API : génération et manipulation de sons en temps réel

ArrayBufferView / Blob / File : créer/manipuler/sauver des fichiers/flux binaires

Il n'est pas possible d'accéder directement aux fichiers sur le système du client (PC/mobile): il faut que l'utilisateur le sélectionne dans un input file, ou qu'il l'enregistre manuellement.

BroadcastChannel : communication "one-to-many" entre browsing contexts (iframes, onglets, fenêtres, etc); cf window.postMessage pour le "one-to-one"

Cache API : gérer vous-même le cache du navigateur

Cette API est à éviter: tout est déjà présent dans le cache HTTP en général , vous n'avez plus qu'à apprendre à l'utiliser.

Canvas API : dessiner quelque chose en 2D ou 3D

Ne vous jetez pas dessus pour faire votre jeu web: canvas ne sert qu'au dessin arbitraire, pas pour créer une interface, des boutons, etc.

Crypto API : fonctions de hashage, cryprographie, etc. Vous n'en aurez probablement pas besoin.

Si vous avez besoin de cette API, alors assurez-vous d'abord de ne pas réinventer (mal!) des systèmes de sécurité déjà existants (et qui, eux, sont bien conçus et implémentés)

window.crypto.subtle .digest('sha-256', new TextEncoder('ascii').encode('Hello, world!')) .then(h => console.log( Array.from(new Uint8Array(h)) .map(e => e.toString(16)) .join('')));
Hashage SHA256 sans aucun framework!

CSS Object Model (CSSOM) : manipulations du CSS via javascript

Attention à ne pas la sur-utiliser: le JS ne doit pas servir à faire du rendu CSS!

Document : une API vaste, dont document.querySelector remplace l'ancien $() de jQuery pour sélectionner un élément

scrollIntoView : fait défiler la vue jusqu'à rendre l'élément ciblé visible (avec des options: en haut, au centre, défilement doux, etc)

DOMParser : crée un arbre (document fragment) HTML à partir d'une string (remplace $()).

Fullscreen API : passe une page/un élément en plein écran (cf :fullscreen )

Gamepad API : accéder aux manettes éventuellement branchées à la machine

Si vous allez jusqu'à cette API, curiosité mise à part, privilégiez l'utilisation d'un SDK.

Géolocalisation : accès aux donnees GPS du terminal

L'utilisateur peut refuser cette localisation: ne soyez pas intrusif sans raison valable dans le jeu!

Intersection Observer : détecte quand un élément DOM est "visible à l'écran"

IndexedDB API : stocke de grandes quantités de données dans le navigateur (des fichiers).

Ne la sur-utilisez pas, car elle n'est pas triviale à metttre en place, et elle a quand même une limite!

MediaQueryList : détecter les changements de dimensions, ratio, orientation, etc du viewport (fenêtre). Voir aussi l'API Screen.

Cette API sera souvent inutile car le CSS propose déjà des media queries.

MediaDevices API : accès au micro et à la caméra (s'il y en a)

Mutation Observer : exécute une callback à l'ajout/modification/suppression d'un noeud/attribut HTML.

Cette API est très utile dans un UserScript (plugin de navigateur).

Notification : afficher des notifications (la forme dépend du support: PC, mobile, etc)

A moins d'être vraiment justifier, les notifications sont souvent refusées par les utilisateurs.

Server Side Events : réagir quand le serveur envoie des données au navigateur (un genre de "push").

Service Worker / Web Worker : exécuter des tâches de fond dans un "thread" séparé de la page web (calculs persistants), ou de gérer tout le traffic réseau du jeu (à éviter: ce n'est pas votre rôle)

Cette API est très délicate à utiliser: la mise à jour du Service Worker n'est pas triviale.

Speech API : reconnaissance/synthèse vocale

Un voice actor ("doubleur") donnera bien plus de vie à votre jeu web qu'un synthétiseur vocal.

Ne l'utilisez pas pour remplir, par la voix, des champs textes: c'est le rôle du navigateur de le faire!

URL : API permettant la manipulation d'urls.

Donc, n'utilisez plus jamais "a=b&c=d".indexOf("&")!

Constraint Validation : décrit précisément les conditions de validité d'un <input>

Privilégiez les attributs natifs avant de recourrir à cette API complexe.

Vibration API : fait vibrer le terminal, s'il en est capable (mobile, tablette, montre)

WebXR Device API (VR/AR) : accès aux données de réalité virtuelle ou de réalité augmentée (bonne chance!)

Web Assembly : faire (en gros) tourner du code C++ dans le navigateur.

Mon conseil? N'allez pas aussi loin!

Web Components : définir des tags et des attributs customs

Je pense, personnellement, que cette API n'est pas utile à un site web: le standard HTML contient déjà tout ce qui vous est nécessaire comme tags/attributs HTML, et les quelques besoin supplémentaires seront largement couverts par deux-trois fonctions JS couplées à des document.querySelector(All).

WebRTC : communication directe entre eux deux navigateurs, sans passer par le serveur!

La gestion d'un tel réseau décentralisé est très complexe (donc, à éviter), et sera souvent impossible directement (réseaux NAT): vous aurez besoin d'un serveur intermédiaire dans la plupart des cas.

WebSocket : communication temps réelle et bi-directionnelles entre le navigateur et le serveur.

Si vous utilisez PHP, cette API sera trop complexe à mettre en place: laissez tomber, ou changez de techno côté serveur.

XPath

Il est possible d'utiliser des expressions XPath en Javascript, pour sélectionner des éléments de la page. Face aux sélecteurs CSS, les sélecteurs XPath ont l'avantage de proposer des axes descendants: vous pourrez sélectionner tous les paragraphes qui contiennent un passage en gras par exemple. Voyez la doc du MDN sur XPath et la sélection d'un élément d'un page via XPath via document.createExpression pour plus d'informations.

Accessibilité

Tout ce qui est bricolé en Javascript n'est pas facilement accessible. Les jeux à base de canvas seront très difficiles à porter sur d'autres supports (mobile, tablette, PC, lecteur d'écran ou commande vocale) et risquent d'amener énormément de maintenance (présente et à venir).

La reconnaissance vocale ne vois pas les éléments JS de la page
La page JS vue par une reconnaissance vocale

AJAX n'est pas indispensable

Polymer encore moins…
Ne recodez pas un navigateur dans votre site web via Javascript. Usez des iframe si besoin, et assurez-vous idéalement que votre jeu reste utilisable même si vous dégagez votre Javascript. Vous réduirez ainsi considérablement votre charge de travail et de maintenance.

XMLHttpRequest

Dans les cas où AJAX vous serait nécessaire, oubliez jQuery et servez-vous directement de XMLHttpRequest (l'objet natif pour AJAX). Vous pourrez comprendre et piloter intégralement vos requêtes client/serveur, headers HTTP inclus (entre autres). Jetez aussi un oeil sur les autres API comme fetch() et sendBeacon

Il est possible de faire des pages dynamiques sans AJAX! Voir la démo d'un formulaire (+popin) sans AJAX

Non, utiliser un framework JS ne règle pas le problème de la maintenance: vous allez au contraire devoir gérer les soucis de navigateur (compatibilité), et les soucis du framework (montées de version).

FormData

L'API FormData peut se coupler à XMLHttpRequest pour permettre à l'utilisateur d'entrer des informations (via un formulaire classique), puis de récupérer ces informations dans votre code JS, et de les transférer au serveur via XMLHttpRequest. Vous aurez alors la possibilité de traiter la réponse du serveur dans votre code JS.

Ajouter un BOM

Pour certains fichiers UTF-8, il peut être nécessaire d'ajouter un BOM lorsqu'un javascript génère le contenu du fichier (histoire que ce dernier soit bien lu comme du UTF-8). Pour cela, préfixez simplement les données du Blob par \uFEFF, qui est le caractère UTF-8 générant le BOM binaire 0xEF 0xBB 0xBF . Si le BOM est plus exotique, vous pouvez passer par un Uint8Array.

new Blob(["\ufeff", fileData], {type: 'text/csv'}) var myBom = new Uint8Array(3); myBom[0] = 0xef; myBom[1] = 0xbb; myBom[2] = 0xbf; var blob = new Blob([myBom, fileData], {type: 'text/csv'});
Ajouter un BOM à un fichier en JS

Optimiser Javascript

Liens