Skip to content

Commit ca437e6

Browse files
committed
Fix: fetch numero on parcel section search
1 parent 91efd32 commit ca437e6

File tree

2 files changed

+146
-26
lines changed

2 files changed

+146
-26
lines changed

src/packages/CSS/Controls/SearchEngine/GPFadvancedSearchEngine.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ form[id^=GPAdvancedForm-] select option.option {
8585
form[id^=GPAdvancedForm-ParcelAdvancedSearch-] .GPautoCompleteList {
8686
display: none;
8787
z-index: 1;
88-
background-color: #fff;
8988
padding: 0;
9089
}
9190
form[id^=GPAdvancedForm-ParcelAdvancedSearch-] input[aria-expanded="true"] ~ .GPautoCompleteList {

src/packages/Controls/SearchEngine/ParcelAdvancedSearch.js

Lines changed: 146 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,14 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
8383
/** Show error message for a given input
8484
* @param {String} name Input name
8585
* @param {String} [message] Message to show (if none remove message)
86+
* @param {String} [what="error"] Message type (error, warning, info)
8687
* @private
8788
*/
88-
_showMessage (name, message) {
89+
_showMessage (name, message, what) {
8990
const div = this.element.querySelector("[name='" + name + "']").parentElement.querySelector(".GPMessagesGroup");
9091
if (message) {
9192
const msg = document.createElement("p");
92-
msg.className = "fr-message fr-message--error";
93+
msg.className = "fr-message fr-message--" + (what || "error");
9394
msg.textContent = message;
9495
div.innerHTML = "";
9596
div.appendChild(msg);
@@ -98,6 +99,38 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
9899
}
99100
}
100101

102+
/** Change the section
103+
* @private
104+
*/
105+
setSection () {
106+
const prefix = this.prefixInput.value;
107+
const section = this.sectionInput.value;
108+
this.numberList.innerHTML = "";
109+
this._showMessage("section", "chargement en cours", "info");
110+
this._fetchCadastre(this.communeId, prefix, section).then(data => {
111+
this._showMessage("section", "");
112+
const section = this.sectionInput.value;
113+
if (data && data.features && data.features[0].properties.section === section) {
114+
this.numberInput.focus();
115+
const numbers = [];
116+
data.features.forEach(numero => numbers.push(numero.properties.numero));
117+
// Sort numbers
118+
numbers.sort().forEach(numero => {
119+
const option = document.createElement("li");
120+
option.value = option.textContent = numero.replace(/^0{1,4}/g,"");
121+
option.addEventListener("click", () => {
122+
this.numberInput.value = option.value;
123+
this._onSearch();
124+
this.numberInput.blur();
125+
this.numberInput.ariaExpanded = "false";
126+
});
127+
this.numberList.appendChild(option);
128+
});
129+
this.filterListNumber();
130+
}
131+
});
132+
}
133+
101134
/**
102135
* Show sections for a given prefix
103136
* @param {String} prefix Prefix code
@@ -110,10 +143,14 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
110143
section.value = "";
111144
section.textContent = "Sélectionner une section";
112145
this.sectionInput.appendChild(section);
146+
let previous = "";
113147
this.feuilles[prefix].sort().forEach(key => {
114-
const section = document.createElement("option");
115-
section.value = section.textContent = key;
116-
this.sectionInput.appendChild(section);
148+
if (key !== previous) {
149+
const section = document.createElement("option");
150+
section.value = section.textContent = key;
151+
this.sectionInput.appendChild(section);
152+
previous = key;
153+
}
117154
});
118155
this.sectionInput.removeAttribute("disabled");
119156
this.sectionInput.focus();
@@ -133,8 +170,10 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
133170
this.communeId = id;
134171
prefixInput.innerHTML = "";
135172
if (id) {
173+
this._showMessage("commCode", "chargement en cours", "info");
136174
// Fetch prefixes and sections for the selected commune
137-
this._fetchFeuille(id).then(data => {
175+
this._fetchCadastre(id).then(data => {
176+
this._showMessage("commCode", "");
138177
this.feuilles = {};
139178

140179
data.features.forEach(feuille => {
@@ -143,10 +182,14 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
143182
}
144183
this.feuilles[feuille.properties.com_abs].push(feuille.properties.section);
145184
});
185+
let previous = "";
146186
Object.keys(this.feuilles).sort().forEach(key => {
147-
const prefix = document.createElement("option");
148-
prefix.value = prefix.textContent = key;
149-
prefixInput.appendChild(prefix);
187+
if (key !== previous) {
188+
const prefix = document.createElement("option");
189+
prefix.value = prefix.textContent = key;
190+
prefixInput.appendChild(prefix);
191+
previous = key;
192+
}
150193
});
151194
this.setFeuille("000");
152195
});
@@ -223,13 +266,15 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
223266
if (index >= autoOptions.length) {
224267
index = -1;
225268
}
269+
e.preventDefault();
226270
break;
227271
}
228272
case "ArrowUp": {
229273
index--;
230274
if (index < -1) {
231275
index += autoOptions.length +1;
232276
}
277+
e.preventDefault();
233278
break;
234279
}
235280
case "Enter": {
@@ -238,16 +283,13 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
238283
autoOptions[index].click();
239284
index = -1;
240285
}
241-
e.preventDefault();
242-
e.stopPropagation();
243286
break;
244287
}
245288
default: {
246289
break;
247290
}
248291
}
249292
if (selectedIndex !== index) {
250-
e.preventDefault();
251293
// Update selected option
252294
autoOptions[selectedIndex]?.classList.remove("active");
253295
selectedIndex = index;
@@ -261,9 +303,8 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
261303

262304
// Show autocomplete on input
263305
comCodeInput.addEventListener("keyup", e => {
264-
e.preventDefault();
265-
e.stopPropagation();
266306
if (["ArrowUp", "ArrowDown", "Enter", "Escape"].includes(e.key)) {
307+
e.preventDefault();
267308
return;
268309
}
269310
showAutocomplete(e);
@@ -284,18 +325,22 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
284325
} else {
285326
this._clearMessages();
286327
}
328+
this._showMessage("commCode", "chargement en cours", "info");
287329
this._fetchCommuneData(comCodeInput.value).then(data => {
330+
this._showMessage("commCode", "");
288331
// Clear previous suggestions
289332
autocompleteList.innerHTML = "";
290333
communeName = "";
291334
if (data.length === 0) {
292335
// errror message
336+
this._showMessage("commCode", "Aucune commune ne correspond à ce code INSEE ou code postal.");
337+
this.setCommune();
293338
} else if (data.length === 1) {
294339
communeName = comCodeInput.value = `${data[0].code} (${data[0].nom})`;
295340
this.setCommune(data[0].code);
296341
} else {
297342
data.forEach(commune => {
298-
const type = commune.codesPostaux ? "code postal" : "code INSEE";
343+
const type = commune.codesPostaux ? "code INSEE" : "code postal";
299344
const option = document.createElement("li");
300345
option.className = "GPautoCompleteOption";
301346
option.setAttribute("role", "option");
@@ -319,14 +364,56 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
319364
prefixInput.addEventListener("change", () => {
320365
this.setFeuille(prefixInput.value);
321366
});
322-
// Fetch parcelles
367+
// Fetch parcelles number
323368
sectionInput.addEventListener("change", () => {
324369
if (sectionInput.value) {
325370
this.numberInput.removeAttribute("disabled");
371+
this.setSection();
326372
} else {
327373
this.numberInput.setAttribute("disabled", "disabled");
328374
}
329375
});
376+
377+
// Handle listbox for number input
378+
this.numberInput.addEventListener("focus", () => {
379+
this.numberInput.ariaExpanded = "true";
380+
});
381+
this.numberInput.addEventListener("blur", (e) => {
382+
if (e.relatedTarget !== this.numberList) {
383+
this.numberInput.ariaExpanded = "false";
384+
}
385+
});
386+
387+
// Filter number list on keyup
388+
this.numberInput.addEventListener("keyup", (e) => {
389+
this.filterListNumber();
390+
if (e.key === "Enter") {
391+
this.numberInput.ariaExpanded = "false";
392+
this.numberInput.blur();
393+
}
394+
});
395+
}
396+
397+
398+
/** Filter listbox options
399+
*/
400+
filterListNumber () {
401+
const filter = this.numberInput.value.toUpperCase();
402+
const options = this.numberList.querySelectorAll("li");
403+
let hasNumber = false;
404+
options.forEach(option => {
405+
if (option.textContent.toUpperCase().indexOf(filter) > -1) {
406+
option.style.display = "";
407+
hasNumber = true;
408+
} else {
409+
option.style.display = "none";
410+
}
411+
});
412+
if (!hasNumber) {
413+
this._showMessage("numero", "Aucun numéro de parcelle ne correspond à cette saisie.");
414+
} else {
415+
this._showMessage("numero", "");
416+
}
330417
}
331418

332419
/**
@@ -401,16 +488,21 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
401488
return Promise.all(responses.map(res => res.json())).then(json => {
402489
return json[0].concat(json[1]);
403490
});
491+
}).catch(error => {
492+
this._showMessage("commCode", "Une erreur est survenue lors de la récupération des données de la commune.");
493+
return [];
404494
});
405495
}
406496

407497
/**
408498
* Récupère les feuilles cadastrales d'une commune via le WFS Geopf
409499
* @private
410500
* @param {String} code Code INSEE de la commune
411-
* @returns
501+
* @param {String} [prefix] Préfixe de la parcelle
502+
* @param {String} [section] Section de la parcelle
503+
* @returns {Promise} Promesse avec les données GeoJSON
412504
*/
413-
async _fetchFeuille (code) {
505+
async _fetchCadastre (code, prefix, section) {
414506
const domtom = ["97","98"].includes(code.slice(0,2));
415507
const dep = code.slice(0, domtom ? 3 : 2);
416508
const com = code.slice(domtom ? 3 : 2, 5);
@@ -419,16 +511,33 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
419511
service : "WFS",
420512
version : "2.0.0",
421513
request : "GetFeature",
422-
typename : "CADASTRALPARCELS.PARCELLAIRE_EXPRESS:feuille",
514+
typename : "CADASTRALPARCELS.PARCELLAIRE_EXPRESS:" + (section ? "parcelle" : "feuille"),
423515
outputFormat : "application/json",
424516
srsName : "CRS:84",
425517
count : "1000",
426-
propertyName : "com_abs,section",
427-
cql_filter : `code_dep='${dep}' and code_com='${com}'`
518+
propertyName : section ? "com_abs,section,numero" : "com_abs,section",
519+
cql_filter : `code_dep='${dep}' and code_com='${com}'` + (section ? ` and com_abs='${prefix}' and section='${section}'` : "")
428520
};
429521
const queryString = new URLSearchParams(params).toString();
430522
const fullUrl = url + queryString;
431-
const response = await fetch(fullUrl);
523+
// Abort previous request
524+
if (this.controller) {
525+
this.controller.abort();
526+
}
527+
// New request
528+
this.controller = new AbortController();
529+
const response = await fetch(fullUrl, {
530+
headers : {
531+
"Content-Type" : "application/json",
532+
},
533+
signal : this.controller.signal
534+
}).catch(error => {
535+
return null;
536+
});
537+
this.controller = null;
538+
if (!response) {
539+
return {};
540+
}
432541
const data = await response.json();
433542
return data;
434543
}
@@ -504,9 +613,18 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
504613
numberInput.name = "numero";
505614
numberInput.title = "Numéro de la parcelle";
506615
numberInput.autocomplete = "off";
616+
numberInput.ariaExpanded = "false";
507617
numberInput.id = Helper.getUid("ParcelAdvancedSearch-number-");
508618
numberInput.setAttribute("disabled", "disabled");
509-
this._getLabelContainer("Numéro*", "fr-input-group", numberInput, "");
619+
const numDiv = this._getLabelContainer("Numéro*", "fr-input-group", numberInput, "");
620+
621+
const numberList = this.numberList = document.createElement("ul");
622+
numberList.className = "GPautoCompleteList";
623+
numberList.id = Helper.getUid("GPautoCompleteList-");
624+
numberList.setAttribute("role", "listbox");
625+
numberList.setAttribute("tabindex", "-1");
626+
numberList.setAttribute("aria-label", "Propositions");
627+
numDiv.insertBefore(numberList, numberInput.nextSibling);
510628
}
511629

512630
/** Do search
@@ -515,7 +633,9 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
515633
* @param {PointerEvent} e Événement de soumission
516634
*/
517635
_onSearch (e) {
518-
super._onSearch(e);
636+
if (e) {
637+
super._onSearch(e);
638+
}
519639

520640
this._clearMessages();
521641

@@ -526,7 +646,7 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
526646
const section = this.sectionInput.value;
527647
const number = this.numberInput.value;
528648
if (!prefix) {
529-
this._showMessage("prefix", "Le préfixe est obligatoire.");
649+
// this._showMessage("prefix", "Le préfixe est obligatoire.");
530650
return;
531651
} else if (!section) {
532652
this._showMessage("section", "La section est obligatoire.");
@@ -558,6 +678,7 @@ class ParcelAdvancedSearch extends AbstractAdvancedSearch {
558678
_onErase (e) {
559679
super._onErase(e);
560680
this.setCommune();
681+
this._clearMessages();
561682
}
562683

563684
}

0 commit comments

Comments
 (0)