jolie beau et ajax

This commit is contained in:
Yasder5 2026-03-02 21:01:46 +01:00
parent 7475c3ce49
commit 42ec68178a
11 changed files with 242 additions and 76 deletions

112
views/_partial/apigeo.tpl Normal file
View file

@ -0,0 +1,112 @@
<!-- Script d'autocomplétion ville/département — API Géo (gouvernement français) -->
<script>
(function () {
const input = document.getElementById('user_location');
const suggestions = document.getElementById('location-suggestions');
let debounceTimer = null;
// Ferme la liste si on clique ailleurs
document.addEventListener('click', function (e) {
if (!input.contains(e.target) && !suggestions.contains(e.target)) {
hideSuggestions();
}
});
input.addEventListener('input', function () {
const query = this.value.trim();
clearTimeout(debounceTimer);
if (query.length < 2) {
hideSuggestions();
return;
}
// Délai de 300 ms pour éviter trop d'appels API
debounceTimer = setTimeout(function () {
fetchCities(query);
}, 300);
});
// Navigation clavier dans la liste
input.addEventListener('keydown', function (e) {
const items = suggestions.querySelectorAll('.list-group-item');
const active = suggestions.querySelector('.list-group-item.active');
let index = Array.from(items).indexOf(active);
if (e.key === 'ArrowDown') {
e.preventDefault();
if (index < items.length - 1) setActive(items, index + 1);
} else if (e.key === 'ArrowUp') {
e.preventDefault();
if (index > 0) setActive(items, index - 1);
} else if (e.key === 'Enter' && active) {
e.preventDefault();
selectItem(active.dataset.value);
} else if (e.key === 'Escape') {
hideSuggestions();
}
});
function fetchCities(query) {
// On cherche par nom de commune, on récupère aussi le département
const url = 'https://geo.api.gouv.fr/communes?nom=' + encodeURIComponent(query)
+ '&fields=nom,departement&boost=population&limit=8';
fetch(url)
.then(function (res) { return res.json(); })
.then(function (data) { renderSuggestions(data); })
.catch(function () { hideSuggestions(); });
}
function renderSuggestions(cities) {
suggestions.innerHTML = '';
if (!cities || cities.length === 0) {
hideSuggestions();
return;
}
cities.forEach(function (city) {
const dept = city.departement
? city.departement.nom + ' (' + city.departement.code + ')'
: '';
const label = city.nom + (dept ? ' — ' + dept : '');
// Valeur stockée : "Ville (Département)"
const value = city.nom + (city.departement ? ' (' + city.departement.nom + ')' : '');
const li = document.createElement('li');
li.className = 'list-group-item list-group-item-action py-2 px-3';
li.style.cursor = 'pointer';
li.dataset.value = value;
li.textContent = label;
li.addEventListener('mousedown', function (e) {
// mousedown avant blur pour éviter que la liste disparaisse avant le clic
e.preventDefault();
selectItem(value);
});
suggestions.appendChild(li);
});
suggestions.style.display = 'block';
}
function selectItem(value) {
input.value = value;
hideSuggestions();
}
function hideSuggestions() {
suggestions.style.display = 'none';
suggestions.innerHTML = '';
}
function setActive(items, index) {
items.forEach(function (item) { item.classList.remove('active'); });
items[index].classList.add('active');
input.value = items[index].dataset.value;
}
})();
</script>