[JavaScript] Comment mettre en place une saisie d’adresse prédictive gratuitement
[content-egg module=Amazon template=list]
Très à la mode depuis maintenant quelques années, la saisie d’adresse prédictive a le
vent en poupe. Et il suffit d’aller faire un tour sur n’importe quel gros site
du moment pour voir que cette fonctionnalité est présente. Alors si vous
souhaitez faire de même sur votre site, je vous propose un petit tutoriel pour
mettre en place cette solution en JavaScript et surtout GRATUITEMENT.
C’est quoi la saisie prédictive d’adresse ?
Avant de vous dire comment l’implémenter, il serait peut-être bon d’expliquer à ceux qui ne le sauraient pas ce qu’est la saisie prédictive d’adresse. C’est tout bête. Dans un formulaire, au lieu de demander à l’internaute de saisir son adresse, son code postal et sa ville, il n’y a plus qu’un seul champ. Et au fur et à mesure où l’internaute saisit son adresse, un ensemble de propositions s’affichent à l’écran et il n’a plus qu’à sélectionner la bonne. C’est rapide, c’est efficace et c’est magique ! Vous pouvez par exemple faire un tour chez just-eat.fr où on vous demande votre adresse dès la page d’accueil pour afficher la liste des restaurants autour de chez vous. C’est typiquement le genre d’application où la saisie d’adresse prédictive est pertinente, voir même primordiale.
Des solutions existent
Plusieurs solutions existent pour implémenter ce genre de
fonctionnalités. Malheureusement, les plus connus, et les plus pertinentes,
sont des solutions payantes. Même
Google, avec son API Google Place, est devenu payant après une bonne dizaine
d’années de gratuité. De quoi mettre le couteau sous la gorge à des
utilisateurs qui ont pris leur habitude et qui se sont retrouvé au pied du mur.
Mais ça, c’est un autre problème qui mériterait bien un article à part entière.
Pour en revenir à notre sujet, si presque toutes les solutions sont payantes,
ce qui peut très bien se comprendre, il existe bien des alternatives gratuites
et c’est du côté du gouvernement qu’il faut regarder.
Merci le gouvernement
Enfin, merci au portail etalab.gouv.fr qui met à disposition tout un tas d’outils en rapport avec les données publiques dont une API qui permet donc de récupérer toutes les adresses du territoire. Par contre, les données récupérées ne sont pas aussi riches que celles proposées par d’autres API, qui utilisent le référentiel de la Poste, mais l’API reste gratuite et fonctionne plutôt bien au final.
Vous pouvez d’ailleurs tester l’API directement depuis votre navigateur. Vous n’avez qu’à renseigner l’adresse ci-dessous et compléter avec le critère de recherche de votre choix après la variable « q »
https://api-adresse.data.gouv.fr/search/?q=33+rue+du+test
Bon, c’est du Json non formaté, mais je suis sûr que certains arrivent à lire dans le Json comme Néo lit dans la matrice…
Bref, passons à la suite
Le formulaire
Pour notre exemple, nous allons mettre en place un formulaire avec un champ qui va servir pour la saisie de l’adresse et trois autres champs pour y stocker l’adresse, le code postal et la ville qui seront récupérés par l’API.
Sous le champ de saisi d’adresse, vous noterez la présence d’une div « selection » qui contiendra la liste des adresses retournées par l’API
<label for="adresse">Saisisez votre adresse :</label> <textarea name="adresse" id="adresse"></textarea> <div id="selection" style="display: none;"> </div> <label for="resAdresse">Adresse :</label> <input type="text" id="resAdresse" disabled> <label for="CP">Code Postal :</label> <input type="text" id="CP" disabled> <label for="Ville">Ville :</label> <input type="text" id="Ville" disabled>
Maintenant, il est temps de passer au plat de résistance
avec du JavaScript pour rendre tout ça vivant
Un peu de JavaScript
Pour pouvoir appeler l’API lorsque l’utilisateur commence à taper du texte, il faut mettre le champ de saisie sur écoute. Et on le fait dès le chargement de la page.
window.onload = function() { document.getElementById("adresse").addEventListener("input", autocompleteAdresse, false); };
Méthode : autocompleteAdresse
function autocompleteAdresse() { var inputValue = document.getElementById("adresse").value; if (inputValue) { fetch(setQuery(inputValue)) .then(function (response) { response.json().then(function (data) { displaySelection(data); }); }); } else { select.style.display = "none"; } };
Dans cette méthode, je vérifie d’abord si l’utilisateur a bien saisi quelque chose. Si ce n’est pas le cas, je cache la div de sélection, sinon j’appelle l’API et je passe le résultat à une autre méthode.
Méthode : displaySelection
function displaySelection(response) { if (Object.keys(response.features).length > 0) { select.style.display = "block"; select.removeChild(select.firstChild); var ul = document.createElement('ul'); select.appendChild(ul); response.features.forEach(function (element) { var li = document.createElement('li'); var ligneAdresse = document.createElement('span'); var infosAdresse = document.createTextNode(element.properties.postcode + ' ' + element.properties.city); ligneAdresse.innerHTML = element.properties.name; li.onclick = function () { selectAdresse(element); }; li.appendChild(ligneAdresse); li.appendChild(infosAdresse); ul.appendChild(li); }); } else { select.style.display = "none"; } }
C’est la méthode que je juge la plus complexe, mais qui reste loin d’être compliqué J
Ici, je récupère l’objet « response » renvoyé par l’API, je vérifie s’il contient des données pour ensuite construire ma liste de choix d’adresses.
Tuto : Angular : Et si on développait un jeu du morpion ?
Dans un premier temps, je crée un objet « ul » que j’insère dans ma div « selection », ensuite je boucle sur le tableau de données contenu dans « response » et je construis un objet li pour chaque ligne qui constitue une adresse.
Enfin, j’applique à l’objet « li » un événement « onCLick() » et je l’insère dans mon objet « ul » précédemment créé.
Ma liste d’adresses
est prête et s’affiche maintenant à l’écran
Méthode : selectAdresse
function selectAdresse(element) { document.getElementById("adresse").value = element.properties.name + "\r\n" + element.properties.postcode + " " + element.properties.city; select.style.display = "none"; document.getElementById("resAdresse").value = element.properties.name; document.getElementById("CP").value = element.properties.postcode; document.getElementById("Ville").value = element.properties.city; }
Cette méthode n’a rien de très compliqué et permet juste de récupérer les différents éléments de l’adresse sélectionnée.
On affiche dans le champ de saisie l’intégralité de l’adresse, les différents éléments dans les trois autres champs et on fait disparaitre la liste de sélection.
Et voilà, c’est terminé, vous venez d’implémenter une saisie d’adresse prédictive.
Code complet
Retrouvez ci-dessous l’intégralité du code de mon exemple. Avec même un peu de CSS pour la forme.
<!DOCTYPE html> <html> <head> <title>Tutoriel JavaScript</title> <meta name="viewport" content="initial-scale=1.0, user-scalable=no"> <meta charset="utf-8"> <style> body { font-family: 'Open Sans', sans-serif; } .dropdown { border: 1px solid black; background-color: white; position: absolute; top: 100%; left: 0; z-index: 100; width: 100%; } .dropdown li { cursor: pointer; list-style-type: none; height: 50px; padding: 5px; display: flex; flex-direction: column; } .dropdown li span { font-weight: bold; } .dropdown li:hover { background-color: lightsteelblue; } .dropdown ul { margin: 0; padding: 0; width: 100%; } .panel { width: 800px; margin: auto; display: flex; flex-direction: column; justify-content: center; } .panel input[type=text] { height: 30px; border-radius: 5px; border: none; border: 1px solid lightgray; font-size: 15px; } .sep { margin-top: 20px; } .test { position: relative; display: flex; flex-direction: column; justify-content: center; } </style> </head> <body> <div class="panel"> <div class="test"> <label for="dresse">Saisisez votre adresse :</label> <textarea name="adresse" id="adresse" rows="3"></textarea> <div id="selection" style="display: none;" class="dropdown"> </div> </div> <div class="sep"></div> <label for="resAdresse">Adresse :</label> <input type="text" id="resAdresse" disabled> <label for="CP">Code Postal :</label> <input type="text" id="CP" disabled> <label for="Ville">Ville :</label> <input type="text" id="Ville" disabled> <label for="adresse">Saisisez votre adresse :</label> <textarea name="adresse" id="adresse"></textarea> <div id="selection" style="display: none;"> </div> <label for="resAdresse">Adresse :</label> <input type="text" id="resAdresse" disabled> <label for="CP">Code Postal :</label> <input type="text" id="CP" disabled> <label for="Ville">Ville :</label> <input type="text" id="Ville" disabled> </div> </body> <script type="text/javascript"> var requestURL = 'https://api-adresse.data.gouv.fr/searchs/?q='; var select = document.getElementById("selection"); window.onload = function() { document.getElementById("adresse").addEventListener("input", autocompleteAdresse, false); }; function displaySelection(response) { if (Object.keys(response.features).length > 0) { select.style.display = "block"; select.removeChild(select.firstChild); var ul = document.createElement('ul'); select.appendChild(ul); response.features.forEach(function (element) { var li = document.createElement('li'); var ligneAdresse = document.createElement('span'); var infosAdresse = document.createTextNode(element.properties.postcode + ' ' + element.properties.city); ligneAdresse.innerHTML = element.properties.name; li.onclick = function () { selectAdresse(element); }; li.appendChild(ligneAdresse); li.appendChild(infosAdresse); ul.appendChild(li); }); } else { select.style.display = "none"; } } function autocompleteAdresse() { var inputValue = document.getElementById("adresse").value; if (inputValue) { fetch(setQuery(inputValue)) .then(function (response) { response.json().then(function (data) { displaySelection(data); }); }); } else { select.style.display = "none"; } }; function selectAdresse(element) { document.getElementById("adresse").value = element.properties.name + "\r\n" + element.properties.postcode + " " + element.properties.city; select.style.display = "none"; document.getElementById("resAdresse").value = element.properties.name; document.getElementById("CP").value = element.properties.postcode; document.getElementById("Ville").value = element.properties.city; } function setQuery(value) { return requestURL + value + "?type=housenumber&autocomplete=1"; } </script> </html>
Commentaires
Laisser un commentaire