Grégory Bourguin
SysReIC - LISIC - ULCO
Javascript (les bases)

IDE

L'IDE que je vous conseille (et que nous utiliserons en salle de TP) est :

Intégration du code

Balise <script>

La balise script permet d'insérer du code Javascript n'importe où dans une page html.

test_01.html
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Premier Javascript</title>
</head>
<body>

<script>
    // déclaration de variable
    var msg = 'hello world !!!'
</script>

Cette page affiche un "hello world" dans la console du navigateur

<script>
    // affichage dans la console du navigateur
    console.log(msg)
</script>

</body>
</html>

Exécution

Le code est exécuté séquentiellement au fur et à mesure de son téléchargement dans le navigateur.

Tip: la console du navigateur peut être trouvée dans les outils de développement.

Script externe

Il est possible de référencer des fichiers externes (.js) contenant les scripts.

test_02.html
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Premier Javascript</title>
</head>
<body>

Cette page affiche un "hello world" dans la console du navigateur

<script src="javascript/hello_world.js"></script>

</body>
</html>
hello_world.js
// déclaration de variable
let msg = 'hello world'

// affichage dans la console du navigateur
console.log(msg)

Variables & Constantes

Déclaration

En Javascript les variables sont typées dynamiquement.

Pour les variables, et pour éviter les ambiguïtés, on utilisera de préférence let.

const PI = 3.14 // NB : il vaudrait mieux utiliser Math.PI
let rayon = 10 // variable avec une portée de bloc
var perimetre = 2 * PI * rayon // variable avec une portée de fonction
console.log(perimetre)

Types (interprétés)

let un_entier = 20
let un_flottant = 3.14
let un_boolen = true
let une_chaine = "Hello"
let un_tableau = ['le Monde', 'World', 'die Welt']
let msg = une_chaine + ' ' + un_tableau[0] // concaténation
console.log(msg)

Objets

Il est possible d'instancier des objets, sans passer par une définition de classe.

let gb = { // séparation des champs par une ','
    first_name: 'grégory', 
    last_name: 'bourguin',
    birth: new Date('1971-10-09'),
    mail: 'gregory.bourguin@univ-littoral.fr'
}

console.log('Prénom : ' + gb.first_name) // une manière d'accéder aux champs
console.log('Nom : ' + gb['last_name']) // une autre manière d'accéder aux champs
console.log("Date de naissance : " + gb.birth.toLocaleDateString('fr-FR'))

Fonction de wrapping

Le problème à résoudre

Il est à noter que la déclaration de variable (& constantes) directement dans la balise script), a pour effet de créer des variables globales.

Cette déclaration globale a 2 principales conséquences :

  • Il est impossible de donner le même nom à plusieurs variables déclarées avec let, ceci même si elles sont déclarées dans des balises script séparées : cela générera une erreur Javascript.

    ex. Tentative de re-déclaration avec let

    <p>Début de la page...</p>
    
    <script> 
        let ma_variable = 100
    </script>
    
    <p>Suite de la page...</p>
    
    <script> 
        let ma_variable = 'Hello!' // REDÉCLARATION : génère une erreur Javascript
    </script>
  • Une 're-déclaration' de variable (le même nom) utilisant var ne crée en réalité pas de nouvelle variable : la valeur de la variable pré-existante est écrasée (...ce qui peut causer des problèmes).

    ex. Déclarations globales (confuses) avec var

    <p>Début de la page...</p>
    
    <script> // script créé au tout début du développement du site 
        var ma_variable = 100
    </script>
    
    <p>Suite de la page...</p>
    
    <script> // script inséré plus tard sans faire attention...
        var ma_variable = 'Hello!'
    </script>
    
    <p>Fin de la page</p>
    
    <script> // script créé au tout début du développement du site 
        console.log(ma_variable + 10)  // on imaginait afficher 110 mais....
    </script>
    Resultat

    Début de la page...

    Suite de la page...

    Fin de la page


La solution : le wrapping

Pour éviter ces problèmes, une bonne pratique consiste à envelopper le code Javascript (qui peut l'être) dans une fonction de wrapping qui va former une 'coquille' limitant la portée des variables.

Le wrapping est une fonction anonyme exécutée directement après sa déclaration.

Ses instructions sont déclenchées dès qu'elles apparaissent dans la page (comme si elles étaient écrites directement dans la balise script), mais les variables qui y sont déclarées ne 'débordent' pas.

ex. avec 2 wrappers

<p>Début de la page...</p>

<script>
// déclaration de la fonction (anonyme) de wrapping 
// (crée une 'coquille' permettant de maîtriser la portée des déclarations) 
(function (){
    
    // code 'wrappé'
    let ma_variable = 100   
    console.log(ma_variable + 10)
     
})() // les 2 dernières parenthèses déclenchent la fonction de wrapping
</script>

<p>Suite de la page...</p>

<script>
// Un autre wrapping
(function (){
    
    // de nouvelles déclaration -> dans un autre contexte = autre variable !
    let ma_variable = 'Hello' 
    console.log(ma_variable + ' World')
     
})()  
</script>
Resultat

Début de la page...

Suite de la page...

Boites de dialogue

Javascript donne accès à de nombreux objets prédéfinis. L'un d'entre eux est l'objet window qui représente une fenêtre (ou un onglet) du navigateur.

Chaque window permet d'ouvrir des boites de dialogues prédéfinies permettant des intéractions basiques avec l'utilisateur. Ces boites de dialogue sont modales, c.a.d. qu'elles empêchent toute autre intéraction avec la window tant qu'elles sont ouvertes.

Attention : ce type de boite de dialogue pouvant être indésirables, il se peut que le navigateur soit configuré pour les bloquer... Dans ce cas, elles ne s'afficheront pas (et les exemples ci-dessous ne fonctionneront pas!)

alert()

let msg = "Hello World !" ;

// ouverture d'une alerte
window.alert(msg) ;

confirm()

// ouverture d'une boite de confirmation et récupération de la réponse
let rep = window.confirm("Voulez-vous continuer ?") ; 
// modal -> l'exécution est stoppée en attendant la réponse...

// 2ème boite de dialogue : message avec la réponse
window.alert('Réponse : ' + rep)

prompt()

// ouverture d'une boite de dialogue et récupération de la réponse
let rep = window.prompt("Quel est ton nom ?") ; 
// modal -> l'exécution est stoppée en attendant la réponse...

// 2ème boite de dialogue : message avec la réponse
window.alert('Bonjour ' + rep + ' !')

Structures de Contrôle

Les structures de contrôle de Javascript sont celles d'un langage de programmation classique.

if

let a_le_permis = true
let est_sobre = false
let a_un_chauffeur = true

let msg = 'Rentre'

if ( (a_le_permis && est_sobre) || a_un_chauffeur){
    msg += ' en voiture'
} else {
    msg += ' à pieds'
}

console.log(msg)

Affectation Ternaire

let a_le_permis = true
let est_sobre = false

let msg = (a_le_permis && est_sobre) ? 'en voiture' : 'à pieds'

msg = 'Rentre ' + msg
console.log(msg)

while

let notes = [18, 15, 6, 20, 12]
let acc = 0

let i = 0
while(i < notes.length){
    acc += notes[i]
    i++
}

let moyenne = acc / notes.length 
console.log("La moyenne est : " + moyenne)

for

let notes = [18, 15, 6, 20, 12]
let acc = 0

for(let i=0 ; i < notes.length ; i++){
    acc += notes[i]
}

let moyenne = acc / notes.length 
console.log("La moyenne est : " + moyenne)

for ... in

let notes = [18, 15, 6, 20, 12]
let acc = 0

for(let i in notes){
    acc += notes[i]
}

let moyenne = acc / notes.length 
console.log("La moyenne est : " + moyenne)

for ... of

let notes = [18, 15, 6, 20, 12]
let acc = 0

for(let n of notes){
    acc += n
}

let moyenne = acc / notes.length 
console.log("La moyenne est : " + moyenne)

.forEach()

let notes = [18, 15, 6, 20, 12]
let acc = 0

notes.forEach((valeur, indice) => { // Le 2eme paramètre (indice) est optionnel
    console.log('Note ' + indice + ' : ' + valeur)
    acc += valeur
})

let moyenne = acc / notes.length 
console.log("La moyenne est : " + moyenne)

Les Fonctions

Les fonctions sont les sous-programmes de Javascript.
Elles permettent de créer du code réutilisable.

Fonction sans paramètre

// déclaration de la fonction
function disBonjour(){
    let msg = "Hello World"
    console.log(msg)
}

// appel de la fonction
disBonjour()
disBonjour()

Fonction avec paramètre(s)

Il est possible (mais pas obligatoire) de donner aux paramètres une valeur par défaut.

// déclaration d'une fonction à 2 paramètres, avec une valeur par défaut pour le 2nd
function disBonjourA(nom, ponctuation='!'){
    console.log('Hello ' + nom + ' ' + ponctuation)
}

// appel de la fonction
disBonjourA('Greg') // utilisation de la valeur par défaut du 2nd paramètre
disBonjourA('Greg', ':)')

Fonction avec valeur de retour (return)

Une fonction peut retourner un résultat grâce à return

// déclaration d'une fonction qui retourne une chaine
function getGreetingMessage(nom, ponctuation='!'){
    let msg = 'Hello ' + nom + ' ' + ponctuation
    return msg // <- l'exécution s'arrête ici ! 
}

// appel de la fonction
let message = getGreetingMessage('Greg')

// TIP : .toUpperCase() met le msg en majuscules
console.log(message.toUpperCase())


NB: Le return stoppe l'exécution de la fonction.

// déclaration d'une fonction qui retourne une chaine
function getGreetingMessage(nom, ponctuation='!'){
    let msg = 'Hello ' + nom + ' ' + ponctuation
    return msg // <- l'exécution s'arrête ici !
    
    // Le code ci-dessous (après le return) ne sera pas exécuté
    msg = 'ce bout de code ne sert à rien' 
}

// appel de la fonction
let message = getGreetingMessage('Greg')

// TIP : .toUpperCase() met le msg en majuscules
console.log(message.toUpperCase())

Introduction aux Évènements

Un atout majeur de Javascript est de pouvoir réagir aux actions de l'utilisateur.

Le navigateur gère les actions de l'utilisateur sous la forme d'évènements (events). Javascript permet d'associer un comportement (une fonction) qui sera déclenché en réaction à chacun de ces évènements.

Pour associer un comportement à une action spécifique de l'utilisateur, il faut ajouter un écouteur dans le gestionnaire d'évènements adéquat de l'objet visé.

  • Chaque objet peut avoir plusieurs gestionnaires d'évènements
  • Chaque gestionnaire d'évènement est associé à un type d'évènement
    (ex. click, mouseover, ...)
  • La fonction associée à l'écouteur sera déclenchée par le gestionnaire à chaque occurrence de l'évènement

Nous verrons dans la suite de ce cours que pratiquement tous les objets présents dans le navigateur sont capables de générer des évènements, et qu'il nous est par conséquent possible d'y réagir...

Écouter un click sur un bouton :

Version HTML : onclick

L'association est faite grâce aux attributs de la balise HTML.

<script>
    // déclaration de la fonction qui sera déclenchée
    function coucou(){
        alert('Coucou !')
    }
</script>

<!-- insertion du bouton.. -->
<!-- ET enregistrement de la fonction -->
<!-- dans le gestionnaire de clicks de CE bouton -->
<button onclick="coucou()">Click Me !</button>
Resultat

Écouter plusieurs types d'évènements :

Version HTML : onclick onmouseover onmouseout

L'association est faite grâce aux attributs de la balise HTML.

<script>
    function btnClick(){
        alert('Click !')
    }
    
    // il est possible de récupérer en paramètre l'évènement généré
    function btnMouseEnter(evt){
        console.log(evt) // optionnel : pour y jeter un oeil dans la console
        let le_bouton = evt.target // récupérer l'objet qui a déclenché l'event 
        le_bouton.style.color='red' // le texte du bouton devient rouge
    }
    
    function btnMouseOut(evt){
        evt.target.style['color']='blue' // variante : le texte du bouton devient bleu
    }
</script>

<!-- insertion du bouton.. -->
<!-- ET enregistrement des fonctions -->
<!-- dans les gestionnaires de CE bouton -->
<button 
    onclick="btnClick()" 
    onmouseenter="btnMouseEnter(event)" 
    onmouseout="btnMouseOut(event)"
>Play with Me !
</button>
Resultat
NB: Dans les exemples ci-avant, j'ai à chaque fois indiqué "Version HTML"...
C'est parce que nous allons maintenant voir qu'on peut faire des choses encore plus puissantes avec la version DOM....