Outils pour utilisateurs

Outils du site


dev:javascript:core:fondamentaux

: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 <script></script> ou bien être présent dans un fichier externe (dans ce cas l'attribut src de la balise <script> est définit ).

Un fichier séparé pour les scripts permet au navigateur de le charger en cache et facilite

Les types

Il existe 8 types de base en Javascript ( 6 types primitifs, Object et Symbol) . Le langage est typé dynamiquement : à l'exécution les variables accueillent n'importe quel type :

"use strict"
// On déclare une variable c et on affecte un entier
let a = 10
 
// on affecte ici une chaine de caractère à la variable "a", c'est syntaxiquement correct
a = "Hello JS"

Les types primitifs :

  • Number : inclus les entiers, les flottants, Infinity, -Infinity et NaN ;
  • BigInt (pour les valeurs au delà de ±(2 53-1) ;
  • String pour les chaines de caractères
  • Boolean
  • null : définit un type à part. Ce n'est pas une référence à un objet non existant ou un pointeur nul. C'est une valeur spéciale qui signifie inconnu, rien ou vide.
  • undefined est un type à part également : il signifie pas de valeur attribuée

Le type Object permet de définir des collections ou des entités complexes et le Le type Symbol est utilisé pour créer des identificateurs uniques pour les objets (singleton).

L'opérateur typeof permet de déterminer le type d'une valeur littérale ou d'une variable :

 
L'instruction typeof null ; retourne “object” : c’est une erreur bien connue du langage conservée pour rétrocompatibilité. null est un type à part, il n’est pas de type “object”. Le comportement l'opérateur typeof dans ce cas peut induire en erreur.

Les commentaires

/**
 * Renvoie x élevé à la n-ième puissance.
 *
 * @param {number} x Le nombre à augmenter.
 * @param {number} n L'exposant doit être un nombre naturel.
 * @return {number} x élevé à la n-ème puissance.
 */
function pow(x, n) {
  ...
}

Ainsi formatés, les commentaires peuvent être extraits et mis en forme par des outils tels que JSDoc 3.

Produire du code auto-descriptif :

  • En nommant correctement les variables ;
  • En factorisant et nommant correctement les fonctions ;

Si un bloc de code a besoin d'être commenté, peut être mérite t il d'être réécrit ou factorisé sous forme d'une fonction. De fait, il existe des algorithmes complexes, et il existe des “paramétrages” intelligents à des fins d’optimisation. Mais généralement, nous devrions essayer de garder le code simple et auto-descriptif.

A Commenter :

  • Architecture globale, vue de haut niveau ;
  • Utilisation de la fonction ;
  • Les solutions importantes, surtout lorsqu’elles ne sont pas immédiatement évidentes.

Commentaires à éviter :

  • Qui disent “comment fonctionne le code” et “ce qu’il fait” ;
  • Ne les mettez que s’il est impossible de rendre le code aussi simple et auto-descriptif qu’il n’en nécessite pas.

Interactions avec la page web

Pour interagir avec les éléments de la page web, le moteur Javascript construit une image du document : le DOM (Document Object Model). Cet objet est stocké dans la variable globale document.

Par défaut, l'exécution du script est lancée dès lecture de la balise <script></script> 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 <script> :

<script src="scripts/main.js" defer></script>

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 = `
  <div>
    <h1>${title}</h1>
      <p>${text}</p>
  </div>
    `;
 
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 :

<div>
  <button id="searchBT">Recercher</button>
</div>

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 :

<form>
  <label for="sform_tinput">Rechercher :</label>
  <input type="text" id="user_input" name="sform_tinput" placeholder="keywords here" required>
  <input type="submit" id="searchBT" value="Go">
</form>

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.

<form>
  <label>Préférence de couleur :</label>
  <input type="radio" id="red" name="couleur" value="red" checked>
  <label for="red">Rouge</label>
  <input type="radio" id="blue" name="couleur" value="blue">
  <label for="blue">Bleu</label>
  <input type="radio" id="green" name="couleur" value="green">
  <label for="green">Vert</label>
</form>

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 :

  • Moka peut être utilisé sur Node.js ou directement dans le navigateur ;
  • La bibliothèque Chai fournit de nombreuses assertions ;
  • Le framework Sinon.js ;

Références

dev/javascript/core/fondamentaux.txt · Dernière modification : 2024/10/13 11:24 de yoann