{{tag>dev javascript js code}} :TODO_DOCUPDATE: ====== Javascript : Fondamentaux ====== Javascript a été conçu pour rendre les pages web dynamiques. Il s'intègre et permet d'interagir avec les documents HTML et le CSS. Un script peut être introduit dans n'importe quelle partie du document HTML. Le code Javascript peut être écrit directement dans le document HTML entre les balises '''' ou bien être présent dans un fichier externe (dans ce cas l'attribut ''src'' de la balise ''%%** cependant selon la position de la balise, le DOM n'est pas complètement construit. Pour s'assurer que le script s'exécute après la définition complète du DOM l'attribut **defer** peut être ajouté à la balise **%% ==== Mettre à jour le contenu ==== De nombreuses méthodes sont disponibles pour récupérer les éléments du DOM notamment : * getElementById() si un attribut **id** est définit sur la balise ; * querySelector() pour utiliser un sélecteur CSS retournant la première correspondance ; * querySelectorAll() pour utiliser un sélecteur CSS retournant toutes les correspondances. Une fois la balise récupérée, on peut par exemple modifier ses attributs avec **setAttribute()**: // on récupère la balise img utilisée pour le logo let b = document.getElementById("logo"); // on modifie l'attribut de la balise baliseImage.setAttribute("alt", "Nouvelle description du logo"); Un ensemble de classes peut être associé à la balise. Pour ajouter ou supprimer une classe : b.classList.add("aClass"); b.classList.remove("anOtherClass"); Pour ajouter du cotenu à la page on pourra notamment utiliser : * la méthode ''createElement()'' ; * la propriété ''innerHTML''. Lorsqu'on souhaite ajouter un élément isolé, la méthode ''createElement()'' est pratique : // création de l'élément let footer_note = document.createElement("p"); // Insertion dans l'arborescence du DOM document.getElementById("containerID").appendChild(footer_note); Pour insérer un nombre plus important d'éléments, on peut utiliser la propriété ''innerHTML'' et l'interpolation de chaines de caractères via les backticks; let title = "Hello World.!" let text = "Voici un exemple de contenu de paragraphe" let d = `

${title}

${text}

`; document.getElementById("containerID").innerHTML = d;
==== Réagir aux évènements ==== La programmation évènementielle consiste à définir du code qui sera exécuté lorsque certains évènements se produisent. Un évènement est un signal envoyé par l’élément HTML lorsque l’utilisateur effectue une action (clic, frappe au clavier, etc). La méthode consiste à : * Indiquer au moteur Javascript les évènements que l'on souhaite écouter grâce à un **eventListener**; * Associer le comportement souhaité (le code) à l’évènement; On crée un bouton dans le document :
Puis on associe un comportement à un évènement possible comme "click" : //syntaxe fonction anonyme let bt = document.getElementById("searchBT"); bt.addEventListener("click", function () { console.log("Vous avez cliqué sur le bouton"); }); //syntaxe équivalente fonction fléchée bt.addEventListener("click", () => { console.log("Vous avez cliqué sur le bouton"); }); Lorsqu'un évènement se produit, la variable ''event'' permet de récupérer des informations sur le contexte de l'évènement comme par exemple : * L' élément sur lequel l'évènement s'est produit (''event.target''); * Les coordonnées de la souris (''event.clientX'' et ''event.clientY''); * La touche du clavier frappée par l'utilisateur (''event.key''); * Etc Ici on journalise dans la console les touches frappées par l'utilisateur lorsque la page est active document.addEventListener('keydown', (event) => { console.log(event.key); }); ==== Traitement des formulaires ==== Les formulaires permettent de regrouper des champs que l'utilisateur peut utiliser pour saisir/transmettre des données à l'application web. Dans le document HTML :
La plupart des champs de formulaire possèdent un attribut **value** qui contient la saisie de l'utilisateur: //Obtenir la valeur saisie par l'utilisateur document.getElementById("user_input").value; Dans le cas des cases à cocher, il faudra vérifier si la propriété **checked** est vraie ; // L'attribut checked est de type bool document.getElementById("anID").checked Les boutons radio partagent l'attribut ''name'' mais un seul bouton radio est actif à la fois.
Pour les traiter, on récupère l'ensemble des boutons radio et on les parcours jusqu'a trouver l'attribut checked à vrai : // Récupère tous les balises input de type bouton radio ayant l'attribut name="couleur" let boutons = document.querySelectorAll('input[name="couleur"]'); let couleur = ""; for (let i = 0; i < boutons.length; i++) { if (boutons[i].checked) { couleur = boutons[i].value; break; } } // Affiche la valeur du bouton radio coché console.log(couleur); Par défaut, lorsque l'utilisateur clique sur le bouton de soumission du formulaire (champ submit) un appel au serveur distant est initié : cela provoque un rechargement de la page qui empêche l'exécution du code Javascript coté client. Si nos traitements ont lieu côté client, ce comportement par défaut n'est pas approprié : dans ce cas, on peut le désactiver. Pour désactiver ce comportement par défaut, il faut : * Écouter cet événement "submit" ; * Empêcher ce comportement grâce à la méthode ''preventDefault()''. const form = document.getElementById("sform"); form.addEventListener("submit", (event) => { // On désactive le rechargement de la page event.preventDefault(); console.log("Il n’y a pas eu de rechargement de page"); }); En général, on vérifie la saisie de l'utilisateur lorsque celui-ci renseigne les champs ou envoie le formulaire : * L’ événement "input" : se déclenche à chaque fois que l’utilisateur tape une lettre dans le champ ; * L’ événement "change" : se déclenche quand l’utilisateur a fini de taper, et sélectionne un autre élément de la page ; * L’ événement "submit" : lorsque l'utilisateur valide le formulaire. ===== Gestion des erreurs ===== Javascript utilise la gestion des exceptions via les instructions **try** / **catch** et **throw**. Ce système permet notamment de reporter/centraliser la gestion des erreurs. function verifyFormField(a_field) { if (a_field.value === "") { throw new Error(`Le champ ${a_field.id} est vide`) } } La fonction définie ci-dessus pourra être appelée n fois dans le code pour chaque champ du formulaire mais selon les besoins, la gestion des erreurs pourra être différente : let form = document.querySelector("form") form.addEventListener("submit", (event) => { try { event.preventDefault(); let name_field = document.getElementById("name"); verifyFormField(name_field); let mail_field = document.getElementById("email"); verifyFormField(mail_field); // traitements du formulaire // ... } catch (error) { //gestion des erreurs centralisée et adaptée à l'application ici console.log("Une erreur est survenue : " + error.message) } }) ===== Tests ===== Frameworks de tests : * [[https://mochajs.org/ | Moka]] peut être utilisé sur Node.js ou directement dans le navigateur ; * La bibliothèque [[https://chaijs.com/|Chai]] fournit de nombreuses assertions ; * Le framework [[https://sinonjs.org/|Sinon.js]] ; ===== Références ===== * [[https://fr.javascript.info|Le Tutoriel JavaScript Moderne]]