Défi

On souhaite mettre à disposition de l'administrateur de notre site une page lui permettant de récupérer l'ensemble des adresses françaises correspondant à sa recherche.

On dispose du code HTML et JavaScript suivant :

1
<!DOCTYPE html>
2
<html>
3
  <head>
4
    <meta charset="utf-8">
5
    <meta name="viewport" content="width=device-width">
6
    <title>repl.it</title>
7
    <link href="style.css" rel="stylesheet" type="text/css" />
8
  </head>
9
  <body>
10
11
    <label for="address">Adresse à rechercher</label>
12
    <input type="text" name="address" id="address">
13
    <button onclick="manageResearch()">Rechercher</button>
14
15
   <div>
16
     <ul id="results">
17
18
     </ul>
19
   </div>
20
21
    <script src="script.js"></script>
22
  </body>
23
</html>
1
function manageResearch () {
2
  console.log('J\'ai été déclenchée')
3
}

L'accès à cette API doit être restreint au possible. Notre administrateur a beau être déjà connecté au site web, on souhaite qu'il décline de nouveau son identité. On souhaite également vérifier qu'il n'est pas un robot en lui faisant effectuer une opération mathématique.

Question

Écrivez les promesses suivantes au sein de fonctions dédiées.

  • Une première promesse demandera à l'utilisateur son nom : s'il répond admin, la promesse sera résolue, sinon elle sera rejetée

  • Une seconde promesse demandera à l'utilisateur combien font 6 x 7 : s'il répond 42, la promesse sera résolue, sinon elle sera rejetée

Ces deux promesses devront toutes les deux être résolues au sein de la fonction manageResearch . Si elles sont toutes les deux validées, un message indiquant que l'utilisateur peut accéder à l'application sera affiché en console, sinon un message indiquant "Accès refusé" sera affiché.

La fonction manageResearch est déclenchée lorsque l'on appuie sur le bouton "Rechercher".

Solution

1
2
3
function askUsername() {
4
  return prompt('Quel est votre nom d\'utilisateur ?')
5
}   
6
7
function askMathOperation() {
8
  return prompt('Combien font 6 x 7')
9
}   
10
11
function success() {
12
  console.log('Vous pouvez accéder à l\'application')
13
}
14
15
function error() {
16
  console.log('Accès refusé')
17
}
18
19
function checkUsername() {
20
  return new Promise((resolve, reject) => {
21
    let username = askUsername()
22
23
    if ('admin' === username) {
24
      resolve()
25
    } else {
26
      reject()
27
    }
28
  })
29
}
30
31
function checkIfIsBot() {
32
  return new Promise((resolve, reject) => {
33
    let result = askMathOperation()
34
    if (42 === parseInt(result)) {
35
      resolve()
36
    } else {
37
      reject()
38
    }
39
  })
40
}
41
42
function manageResearch () {
43
  Promise.all([checkUsername(), checkIfIsBot()]).then(success, error)
44
}
45

Pour effectuer une recherche, on se basera sur l'API suivante : https://geo.api.gouv.fr/adresse.

Si l'on souhaite récupérer les résultats pour l'adresse "8 bd du port", on appellera l'URL suivante : https://api-adresse.data.gouv.fr/search/?q=8+bd+du+port.

En JavaScript, il est possible d'implémenter une URL avec l'objet URL, qui dispose d'une propriété search. Il est possible de définir des paramètres à une requête GET au moyen de l'objet URLSearchParams.

Question

Procédons par étapes, dans un premier temps :

  • Déclarez une constante url contenant l'adresse https://api-adresse.data.gouv.fr/search

  • Au sein d'une nouvelle fonction appelée searchAddress, initialisez votre URL en définissant un nouvel objet de type URLSearchParam. Celui-ci contiendra une propriété q dont la valeur correspondra à la valeur de l'input #address

Vous pourrez vérifier le contenu de l'objet construit grâce à l'instruction suivante : console.log(url.href);.

La fonction searchAddress sera quant à elle appelée au sein de la fonction success précédemment déclarée.

Solution

1
const url = new URL('https://api-adresse.data.gouv.fr/search')
2
3
// ... // 
4
5
function success() {
6
  console.log('Vous pouvez accéder à l\'application')
7
  searchAddress()
8
}
9
10
function searchAddress() {
11
  let params = {q: document.getElementById("address").value}
12
  url.search = new URLSearchParams(params).toString();
13
14
  console.log(url.href);
15
}

Question

Vous disposez de la fonction suivante, permettant d'afficher les résultats sur votre page.

À l'aide de l'API Fetch, appelez l'URL que vous avez construite au sein de la fonction searchAddress et appelez la fonction dont vous disposez en cas de succès.

Vous traiterez l'affichage des erreurs en les affichant en console.

La méthode createTextNode() crée un nœud de texte avec le texte spécifié.

1
function fillResults(data) {
2
  let list = document.getElementById('results')
3
  list.innerHTML = ''
4
  if(undefined !== data.features) {
5
    data.features.forEach(function(element) {
6
      let li = document.createElement('li')
7
      li.appendChild(document.createTextNode(element.properties.label))
8
      list.appendChild(li)
9
    });
10
  }
11
}

Solution

Voici comment la fonction searchAddress a dû être complétée :

1
function searchAddress() {
2
  let params = {q: document.getElementById("address").value}
3
  url.search = new URLSearchParams(params).toString();
4
5
  fetch(url)
6
    .then((response) => {
7
        if(response.ok){
8
            return response.json()
9
        } else {
10
            console.error("Erreur réponse : " + response.status)
11
        }
12
    })
13
    .then((data) => {
14
      fillResults(data)
15
    })
16
    .catch((error) => console.error(error)) //Traitement de l'erreur dans l'appel
17
}

Voici également le script dans sa globalité :

1
const url = new URL('https://api-adresse.data.gouv.fr/search')
2
3
function askUsername() {
4
  return prompt('Quel est votre nom d\'utilisateur ?')
5
}   
6
7
function askMathOperation() {
8
  return prompt('Combien font 6 x 7')
9
}   
10
11
function success() {
12
  console.log('Vous pouvez accéder à l\'application')
13
  searchAddress()
14
}
15
16
function error() {
17
  console.log('Accès refusé')
18
}
19
20
function checkUsername() {
21
  return new Promise((resolve, reject) => {
22
    let username = askUsername()
23
24
    if ('admin' === username) {
25
      resolve()
26
    } else {
27
      reject()
28
    }
29
  })
30
}
31
32
function checkIfIsBot() {
33
  return new Promise((resolve, reject) => {
34
    let result = askMathOperation()
35
    if (42 === parseInt(result)) {
36
      resolve()
37
    } else {
38
      reject()
39
    }
40
  })
41
}
42
43
function manageResearch () {
44
  Promise.all([checkUsername(), checkIfIsBot()]).then(success, error)
45
}
46
47
function searchAddress() {
48
  let params = {q: document.getElementById("address").value}
49
  url.search = new URLSearchParams(params).toString();
50
51
  fetch(url)
52
    .then((response) => {
53
        if(response.ok){
54
            return response.json()
55
        } else {
56
            console.error("Erreur réponse : " + response.status)
57
        }
58
    })
59
    .then((data) => {
60
      fillResults(data)
61
    })
62
    .catch((error) => console.error(error)) //Traitement de l'erreur dans l'appel
63
}
64
65
function fillResults(data) {
66
  let list = document.getElementById('results')
67
  list.innerHTML = ''
68
  if(undefined !== data.features) {
69
    data.features.forEach(function(element) {
70
      let li = document.createElement('li')
71
      li.appendChild(document.createTextNode(element.properties.label))
72
      list.appendChild(li)
73
    });
74
  }
75
}
76