JavaScript

[JavaScript] Comment mettre en place une saisie d’adresse prédictive gratuitement

Par Marc, le 20 décembre 2019, mis à jour le 1 avril 2021 — adresse, html, javascript, tuto — 9 minutes de lecture
Comment mettre en place une saisie d’adresse prédictive gratuitement en javascript

[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.

Comment mettre en place une saisie d’adresse prédictive gratuitement en javascript

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

Comment mettre en place une saisie d’adresse prédictive gratuitement en javascript

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.

Comment mettre en place une saisie d’adresse prédictive gratuitement en javascript

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>

Marc

Développeur full-stack depuis maintenant près de 7 ans, j'ai décidé d'ouvrir ce blog afin de capitaliser mes acquis, essayer de partager mes connaissances, découvrir de nouvelles technologies et surtout échanger avec d’autres développeurs.

Commentaires

Laisser un commentaire

Votre commentaire sera révisé par les administrateurs si besoin.