autocomplete: switch autocomplete.js
Turns out implementing a autocomplete widget from scratch is more tricky than expected. It's a shame no such widget has been implemented part of the HTML standart :(
This commit is contained in:
parent
68434bf446
commit
d0715b0d15
2 changed files with 75 additions and 121 deletions
|
@ -15,6 +15,8 @@
|
||||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
|
||||||
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
|
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
|
||||||
crossorigin="anonymous"></script>
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@10.2.6/dist/autoComplete.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@10.2.6/dist/css/autoComplete.02.min.css">
|
||||||
|
|
||||||
<title>Aquilenet: Éligibilité FTTH</title>
|
<title>Aquilenet: Éligibilité FTTH</title>
|
||||||
<style>
|
<style>
|
||||||
|
@ -63,13 +65,9 @@
|
||||||
<div id="methodAddress" class="collapse testMethods">
|
<div id="methodAddress" class="collapse testMethods">
|
||||||
<h2 class="text-center form-title">Test d'éligibilité par adresse</h2>
|
<h2 class="text-center form-title">Test d'éligibilité par adresse</h2>
|
||||||
<form id="formAddressTest" method="post" action="/test/address">
|
<form id="formAddressTest" method="post" action="/test/address">
|
||||||
<div class="form-group" id="communeForm">
|
<div class="form-group row" id="communeForm">
|
||||||
<label class="form-label" for="communeInput">Commune</label>
|
<label class="form-label col-sm-2 my-1" for="commune-autocomplete">Commune</label>
|
||||||
<input autocomplete="off" type="text" list="communes" name="commune" class="form-control"
|
<input id="commune-autocomplete" class="col-sm-9" type="search" dir="ltr" spellcheck=false autocorrect="off" autocomplete="off" class="form-control" autocapitalize="off"/>
|
||||||
id="communeInput" ondblclick="this.focus();this.select()" aria-describedby="communeHelp"
|
|
||||||
placeholder="Nom de la commune ou code postal">
|
|
||||||
<datalist id="communes">
|
|
||||||
</datalist>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row collapse" id="voieForm">
|
<div class="form-row collapse" id="voieForm">
|
||||||
<div class="col-sm-3 my-1">
|
<div class="col-sm-3 my-1">
|
||||||
|
@ -79,12 +77,9 @@
|
||||||
oninvalid="this.setCustomValidity('Veuillez renseigner le numéro de voie')"
|
oninvalid="this.setCustomValidity('Veuillez renseigner le numéro de voie')"
|
||||||
oninput="setCustomValidity('')">
|
oninput="setCustomValidity('')">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-9 my-1">
|
<div class="col-sm-7 my-1">
|
||||||
<label class="form-label" for="voieInput">Nom de voie</label>
|
<label class="form-label" for="fantoir-autocomplete">Nom de voie</label>
|
||||||
<input autocomplete="off" type="text" name="voie" list="voies" class="form-control" id="voieInput"
|
<input id="fantoir-autocomplete" class="form-control" type="search" dir="ltr" spellcheck=false autocorrect="off" autocomplete="off" autocapitalize="off"/>
|
||||||
aria-describedby="voieHelp" placeholder="Nom de voie">
|
|
||||||
<datalist id="voies">
|
|
||||||
</datalist>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
|
@ -131,94 +126,6 @@
|
||||||
return inputStr;
|
return inputStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to update list of communes (calls backend API)
|
|
||||||
function updateCommunes(search = '') {
|
|
||||||
var api = "addresses/communes?limit=15";
|
|
||||||
if (search != '') {
|
|
||||||
api += "&s=" + search;
|
|
||||||
}
|
|
||||||
fetch(api, { signalCommunes })
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
valueMatch=false;
|
|
||||||
if (JSON.stringify(data) !== JSON.stringify(communes)) {
|
|
||||||
$("#communes").empty();
|
|
||||||
communes = data
|
|
||||||
communes.forEach(commune => {
|
|
||||||
value=commune.codeZip + ' ' + commune.nom
|
|
||||||
$("#communes").append("<option codeInsee=" + commune.codeInsee + " value='" +
|
|
||||||
value + "'></option>");
|
|
||||||
if (value === search) {
|
|
||||||
valueMatch=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (communes.length == 1 || valueMatch) {
|
|
||||||
codeInsee = communes[0].codeInsee;
|
|
||||||
$('#voieForm').collapse('show');
|
|
||||||
} else {
|
|
||||||
$('#voieInput').val('');
|
|
||||||
$('#voieForm').collapse('hide');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error("Error fetching communes:", err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to update list of voies (calls backend API)
|
|
||||||
function updateVoies(search = '') {
|
|
||||||
var api = "addresses/fantoirvoies/" + codeInsee + '?limit=15';
|
|
||||||
if (search != '') {
|
|
||||||
api += "&s=" + search;
|
|
||||||
}
|
|
||||||
fetch(api, { signalVoies })
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
valueMatch=false;
|
|
||||||
if (JSON.stringify(data) !== JSON.stringify(voies)) {
|
|
||||||
$("#voies").empty();
|
|
||||||
voies = Object.entries(data);
|
|
||||||
let voie;
|
|
||||||
for (i in voies) {
|
|
||||||
voie = voies[i]
|
|
||||||
$("#voies").append("<option value='" +
|
|
||||||
voie[0] + "'></option>");
|
|
||||||
if (voie[0] === search) {
|
|
||||||
valueMatch=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (voies.length == 1 || valueMatch) {
|
|
||||||
$('#btnTestAdresse').collapse('show');
|
|
||||||
voie = voies[0]
|
|
||||||
codeRivoli = voie[1]
|
|
||||||
$("#voieInput").val(voie[0]);
|
|
||||||
$('#btnTestAdresse').focus();
|
|
||||||
} else {
|
|
||||||
$('#btnTestAdresse').collapse('hide');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error("Error fetching communes:", err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function fetchWithBackoff (fetchFn, timeout, input) {
|
|
||||||
if(timeout !== null) {
|
|
||||||
clearTimeout(timeout);
|
|
||||||
}
|
|
||||||
if (input.length < 3) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
timeout = setTimeout(() => {
|
|
||||||
const cleanInput = sanitizeInputStr(input);
|
|
||||||
fetchFn(cleanInput);
|
|
||||||
}, 100);
|
|
||||||
return timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#methodAddress').on('show.bs.collapse', function () {
|
$('#methodAddress').on('show.bs.collapse', function () {
|
||||||
$('#communeInput').trigger('input')
|
$('#communeInput').trigger('input')
|
||||||
$('#communeInput').trigger('keyup')
|
$('#communeInput').trigger('keyup')
|
||||||
|
@ -234,26 +141,69 @@
|
||||||
$('#numeroVoieInput').focus();
|
$('#numeroVoieInput').focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
let timeoutCommune = null;
|
const autoCompleteCommune = new autoComplete({
|
||||||
$('#communeInput').on('input', function () {
|
selector: "#commune-autocomplete",
|
||||||
controllerCommunes.abort();
|
placeHolder: "Code postal/nom de commune...",
|
||||||
timeoutCommune = fetchWithBackoff(updateCommunes, timeoutCommune, $(this).val());
|
data: {
|
||||||
});
|
src: async (query) => {
|
||||||
|
const api = "addresses/communes?limit=100";
|
||||||
$('#communeInput').on('input', function () {
|
const reqUrl = query === '' ? api : api + "&s=" + query
|
||||||
if ($(this).val() === '') {
|
const source = await fetch(reqUrl, { signalCommunes });
|
||||||
$('#voieForm').collapse('hide');
|
const data = await source.json();
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
keys: [ "codeZip", "nom" ],
|
||||||
|
},
|
||||||
|
resultList: {
|
||||||
|
element: (list, data) => {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resultItem: {
|
||||||
|
highlight: true
|
||||||
|
},
|
||||||
|
debounce: 300,
|
||||||
|
events: {
|
||||||
|
input: {
|
||||||
|
selection: (event) => {
|
||||||
|
const selection = event.detail.selection.value;
|
||||||
|
autoCompleteCommune.input.value = selection.codeZip + " - " + selection.nom ;
|
||||||
|
codeInsee = selection.codeInsee;
|
||||||
|
$("#voieForm").collapse("show");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let timeoutVoie = null;
|
const autoCompleteFantoir = new autoComplete({
|
||||||
$('#voieInput').on('input', function () {
|
selector: "#fantoir-autocomplete",
|
||||||
controllerVoies.abort();
|
placeHolder: "Nom de la voie...",
|
||||||
timeoutVoie = fetchWithBackoff(updateVoies, timeoutVoie, $(this).val());
|
data: {
|
||||||
});
|
src: async (query) => {
|
||||||
$('#voieInput').on('input', function () {
|
const api = "addresses/fantoirvoies/" + codeInsee + "?limit=100";
|
||||||
if ($(this).val() === '') {
|
const reqUrl = query === '' ? api : api + "&s=" + query
|
||||||
$('#btnTestAdresse').collapse('hide');
|
const source = await fetch(reqUrl, { signalVoies });
|
||||||
|
const data = await source.json();
|
||||||
|
return Object.entries(data).map(e => {return {"name": e[0], "value": e[1]}; });
|
||||||
|
},
|
||||||
|
keys: [ "name" ],
|
||||||
|
},
|
||||||
|
resultList: {
|
||||||
|
element: (list, data) => {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resultItem: {
|
||||||
|
highlight: true
|
||||||
|
},
|
||||||
|
debounce: 300,
|
||||||
|
events: {
|
||||||
|
input: {
|
||||||
|
selection: (event) => {
|
||||||
|
const selection = event.detail.selection.value;
|
||||||
|
autoCompleteFantoir.input.value = selection.name;
|
||||||
|
codeRivoli = selection.value;
|
||||||
|
$('#btnTestAdresse').collapse('show');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,10 @@ body {
|
||||||
text-shadow: dimgray 0 1px 1px;
|
text-shadow: dimgray 0 1px 1px;
|
||||||
background-image: linear-gradient(to bottom, #ffd38c 0%, #ffedd0 51%, #e0e0e0 100%);
|
background-image: linear-gradient(to bottom, #ffd38c 0%, #ffedd0 51%, #e0e0e0 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Autocomplete */
|
||||||
|
|
||||||
|
|
||||||
/* #fda085 51%, */
|
/* #fda085 51%, */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue