Semaine 7 : AJAX & Formulaires - SimplonSt-Gaudens/programme-web-dev-promo-2 GitHub Wiki

Semaine 7

Objectifs

  • Continuer sur Javascript
  • Consolider les acquis

Objectif bonus

  • Publier un article sur Medium (de la veille, ce que vous avez appris pendant la GameJam, etc)

Objectif bonus pour Julien

  • Se créer un compte sur Medium et créer un article

Mardi

Correction des exercices rendus

Veille de la semaine

  • mercredi : media-queries,
  • jeudi : les rôles dans une équipe Agile,
  • vendredi : Merise,
  • lundi : UML.

Ajax

C'est du propre

  • D'habitude, sur une page web, le fonctionnement est asynchrone : l'utilisateur clique, les infos sont envoyées par le navigateur puis traitées par le serveur web. Des infos sont renvoyées par le serveur web et affichées par le navigateur.
  • Avec Ajax, des infos sont envoyées et traitées "en direct".
  • Un exemple? Sur un formulaire classique, vous remplissez les champs, cliquez sur le bouton et recevez des infos en retour (pour savoir si vous avez bien rempli le formulaire, par exemple). Avec Ajax, les infos sont envoyées au fur et à mesure que vous remplissez les champs, sans autre intervention de l'utilisateur.
  • Pour cela, il vous faudra donc du HTML (et du CSS pour que ce soit joli), du javascript (et l'objet XMLHttpRequest), maîtriser le DOM et connaître XML.

XML ?!

  • XML reprend le même objectif que celui qu'on a vu pour JSON : stocker des données dans un fichier. Sauf qu'il utilise pour cela une syntaxe bien précise, avec notamment des balises (comme HTML). Ca donne quelque chose comme ça (en l'indentant, ce sera tout de suite plus lisible... comme HTML) :

    `<?xml version="1.0"?>`
     `<contact-info>`
     `<name>Tanmay Patil</name>`
     `<company>TutorialsPoint</company>`
     `<phone>(011) 123-4567</phone>`
    `</contact-info>`
    

OK mais comment ça marche?

Des liens pour mieux comprendre

Exercices

Le formulaire client

Créer un fichier JSON contenant des informations sur un client (nom, prénom, âge, profession, email, téléphone etc...) Créer une liste déroulante avec les noms des clients de la base et lorsque que vous sélectionnez un client, l'ensemble de ses informations apparaissent plus bas avec AJAX.

Trouve ma ville
La suite

Sur une page, prévoyez les fonctionnalités suivantes :
Step 1 : Météo Afficher la météo de Montpellier (température en °C et description). Utilisez une requête vers OpenWeather.

Step 2 : Adresse Récupérer la latitude et la longitude de Alès. Utiliser une requête vers GoogleMaps Api (pas la peine de clé API si vous ne faites pas bcp de requêtes).

Step 3 : Itinéraire Récupérer le temps et la distance d'un itinéraire de Montpellier à Alès. Utiliser une requête vers GoogleMaps API.

Bonus : Tout-en-un
L'utilisateur saisit une ville pour obtenir :

  • la météo
  • l'heure
  • la latitude et la longitude
  • le temps et la distance depuis Alès.

Bonus ultime : affichez l'heure

Kata

Développez la fonction getMiddle(input_text) :

  • Si input_text contient un nombre impair d'éléments, la fonction renvoie le caractère du milieu.
  • Sinon, elle renvoie les deux caractères du milieu.

Exemples:

  • getMiddle("test") renvoie "es"
  • getMiddle("testing") renvoie "t"
  • getMiddle("middle") renvoie "dd"
  • getMiddle("A") renvoie "A"

Mercredi

On reprend Ajax calmement

function traiteResultat(){
	console.log("resultat", this.responseText);
	var data = JSON.parse(this.responseText);
	console.log('Nom 0', data.participants[0].nom);
}

var requete = new XMLHttpRequest();
requete.onload = traiteResultat;

requete.open("get", "users.txt", true);
requete.send();


{
	"participants":[
		{
			"id":1,
			"nom":"Durant",
			"prenom":"Lea"
		},
		{
			"id":2,
			"nom":"Dupond",
			"prenom":"Joe"
		},
		{
			"id":3,
			"nom":"Martin",
			"prenom":"Jean"
		}
	]
}

⚠️ Une étrangeté est à noter dans ce 1er exemple très basique : la référence à this.responseText`` dans la fonction traiteResultat()`.

En fait, écrit de cette manière, traiteResultat s'éxecute dans le contexte ( aussi appelé scope )ππ de l'objet requete et non pas dans le contexte "global" du script.

En effet, si on essaye de logger this dans la fonction, on s'aperçoit que this renvoie en fait à l'objet XMLHttpRequest...

function traiteResultat(){
	console.log("scope", this);
	// ...
}

C'est une des particularités du javascript 5 : le scope d'une fonction n'est pas forcèment celui dans lequel on déclare la fonction.

Ici le scope dans lequel s'éxecute la fonction après réception des données, et celui de l'objet requete.

Oui et alors ? me direz vous... Et bien le problème, est que, dans l'état, on ne pourra pas appeler les méthodes déclarées dans le contexte globale depuis la fonction traiteResultat()...

La solution ?

  1. Il existe une "obscure" fonction bind() en javascript, qui permet de choisir le contexte dans lequel s'éxecutera une fonction.

  2. on récuperera la valeur de responseText à partir de l'event, ou plutôt le target de l'event.

/* la déclaration du paramètre event est facultative, mais son utilisation nous permet de récupérer
la référence de l'objet XMLHttpRequest, dans la mesure où c'est lui qui émet l'event,
et que par conséquent, c'est lui le target.
*/

function traiteResultat(event){
	console.log("resultat", event.target.responseText);
	var data = JSON.parse(event.target.responseText);
	console.log('Nom 0', data.participants[0].nom);
}

var requete = new XMLHttpRequest();

/* l'ajout de bind(this) permet de définir que l'on veut que
la fonction traiteResultat soit
 executée dans le contexte courant*/
requete.onload = traiteResultat.bind(this);

requete.open("get", "users.txt", true);
requete.send();

Ancienne méthode IE9& -

cf Ajax - OpenClassRoom

function onLoadingState(event){
	console.log('data');
	if (requete.readyState === requete.DONE && requete.status === 200) {
		console.log('resultat', requete.responseText);
		var data = JSON.parse(requete.responseText);
		console.log('Nom 0', data.participants[0].nom);
	}
}

var requete = new XMLHttpRequest();
requete.addEventListener('readystatechange', onLoadingState );

requete.open("get", "users.txt", true);
requete.send();

Jeudi

DRY : Don't Repeat Yourself

Création d'un "template" / boilerplate de dossier pour nouveau projet web

L'idée est de mettre en pratique le principe du DRY. Il est nécessaire d'essayer de repenser et d'améliorer continuellement ses méthodes, outils, organisation... ( sans non plus y passer tout son temps... :) )

Le développement d'un projet web comporte un certain nombre de tâches répétitives. Il existe de nombreux outils, gratuits et opensource (ou pas) qui peuvent nous aider à gagner du temps. Toutefois, même si l'intégration dans son workflow, d'outils standards/référence, "prêt à l'emploi", est progressivement nécessaire, il peut être utile d'apprendre à se créer ses propres "outils".

  • création d'un dossier avec fichiers de base:

    • style-base.css : définition des régles de styles systèmatiques cf [CSSReset]
    • scripts-base.js : avec des fonctions raccourcies ou utilitaires "à la jQuery" ( ex : des fonctions byId(), byTag()... )
    • index.html intégrant les fichiers css et js
  • initialisation git du dossier, et dépôt sur github

  • pour utiliser le template :

    • cloner le projet depuis github git clone http://github.com/VOUS/PROJET.git
    • supprimez le .git rm -rf dossier_template/.git
    • renommez le dossier chargé mv dossier_template/ nouveauProjet/
    • initialisez git dans le nouveau dossier cd nouveauProjet/ ; git init

L'utilisation de ce template pourra être simplifiée en créant par exemple un alias pour lancer toutes ces instructions en une commande. Cela constitue également un petit préambule à l'utilisation des outils d'automatisation front-end modernes ( NPM, Webpack, Grunt, Gulp, ... ).

Les formulaires

On va trouver plein de types de champs :

  • range
  • color
  • hidden
  • time
  • datetime
  • number
  • search
  • tel
  • url

Quelques liens

Exercice

Gestion d'utilisateurs

  • Créez un formulaire d'inscription. Dans celui-ci l'utilisateur est invité à saisir : nom, prénom, login (ne doit pas déjà être utilisé), sexe (bouton radio), mot de passe (au moins huit caractères dont au moins une majuscule, un caractère spécial et un chiffre), date de naissance, ville, mail (valide), url de son site (valide), ses hobbys (max 200 caractères), son numéro de téléphone (XX.XX.XX.XX.XX) ainsi que sa couleur préférée.
  • Bonus : implémenter l'autocomplétion pour la ville.
  • Bonus 2: pas besoin de soumettre le formulaire pour contrôler les champs.
  • Stocker les données récupérées. Ce peut être l'occasion de jeter un oeil au localStorage introduit par HTML5.
  • Créez un formulaire de connexion. L'utilisation saisit un login et un mdp. Si les deux correspondent, on l'autorise à se connecter et on l'accueille avec un message du type : "Bienvenue <prénom> ".

Blog

Développez un mini-moteur de blog permettant de créer et de modifier des articles. La liste des billets et de leurs liens doit être stockées dans un fichier JSON.
Implémentez les pages d'inscription et de connexion développées lundi. N'importe qui peut lire les billets mais seul un utilisateur connecté peut créer un nouveau billet. Quelles fonctionnalités devriez-vous inclure?

Jeudi

Randori

  • Créez une fonction diffBig2() telle que : diffBig2([10, 5, 2]) = 10-5 = 5
  • La fonction, en partant d'une liste de nombres, renvoie la différence entre les deux plus grands.
  • Faites-le sans utiliser sort().

Vendredi

Cadeau bonux : travailler à plusieurs avec Git

⚠️ **GitHub.com Fallback** ⚠️