Skip to content

Commit c01c5fe

Browse files
authored
Merge pull request #796 from MTES-MCT/feature/695-adresse-autocomplete
[FO - Signalement] Refonte composant autocompletion
2 parents 140d5f3 + aa3011d commit c01c5fe

File tree

5 files changed

+151
-35
lines changed

5 files changed

+151
-35
lines changed

assets/controllers/component_search_address.js

+110-12
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ $(function() {
88
function initSearchAddress() {
99
var idTimeoutInputAddress = null;
1010
var ajaxObject = null;
11+
var selectedSuggestionIndex = -1;
12+
var isAutocompleteOpen = false;
13+
14+
$(document).on('click', function(event) {
15+
if (!$(event.target).closest('.fr-autocomplete-list').length && isAutocompleteOpen) {
16+
closeSuggestions();
17+
}
18+
});
1119

1220
$('input#rechercheAdresse').on('input', function() {
1321
if (idTimeoutInputAddress !== null) {
@@ -17,7 +25,7 @@ function initSearchAddress() {
1725
ajaxObject.abort();
1826
}
1927

20-
$('#rechercheAdresseListe select').empty();
28+
$('#rechercheAdresseListe').empty();
2129
$('#rechercheAdresseIcon .fr-icon-timer-line').show();
2230
$('#rechercheAdresseIcon .fr-icon-map-pin-2-line').hide();
2331

@@ -30,6 +38,7 @@ function initSearchAddress() {
3038
ajaxObject = $.ajax({
3139
url: 'https://api-adresse.data.gouv.fr/search/?q=' + searchField
3240
}).done(function(jsonData) {
41+
let ariaPosinset = 1;
3342
for (let feature of jsonData.features) {
3443
let adresseLabel = feature.properties.label;
3544
let adresseName = feature.properties.name;
@@ -46,7 +55,23 @@ function initSearchAddress() {
4655
elementData += ' data-citycode="'+adresseCityCode+'"';
4756
elementData += ' data-geoloclat="'+adresseGeolocLat+'"';
4857
elementData += ' data-geoloclng="'+adresseGeolocLng+'"';
49-
$('#rechercheAdresseListe select').append( '<option '+elementData+' class="fr-mb-1v fr-p-1v">'+adresseLabel+'</option>' );
58+
59+
const setSize = jsonData.features.length;
60+
$('#rechercheAdresseListe')
61+
.append(
62+
'<li '
63+
+ elementData
64+
+ ' class="fr-col-12 fr-p-3v fr-text-label--blue-france fr-autocomplete-suggestion"'
65+
+ ' role="option" tabindex="-1"'
66+
+ ' aria-selected="false"'
67+
+ ' aria-posinset="' + ariaPosinset + '"'
68+
+ ' aria-setsize="' + setSize + '"'
69+
+ '>'
70+
+ adresseLabel
71+
+ '</li>');
72+
73+
++ariaPosinset;
74+
5075
$('#rechercheAdresseListe').show();
5176
$('#rechercheAdresseIcon .fr-icon-timer-line').hide();
5277
$('#rechercheAdresseIcon .fr-icon-map-pin-2-line').show();
@@ -59,8 +84,10 @@ function initSearchAddress() {
5984
});
6085
}
6186

62-
$('#rechercheAdresseListe select option').on('click', function() {
63-
let formPrefix = ($('#signalement_history_adresse').length > 0) ? 'signalement_history' : 'signalement_front';
87+
$('#rechercheAdresseListe li').on('click', function() {
88+
let formPrefix = ($('#signalement_history_adresse').length > 0)
89+
? 'signalement_history'
90+
: 'signalement_front';
6491
$('#rechercheAdresse').val($(this).data('label'));
6592
$('#' + formPrefix + '_adresse').val($(this).data('name'));
6693
$('#' + formPrefix + '_codePostal').val($(this).data('postcode'));
@@ -75,20 +102,27 @@ function initSearchAddress() {
75102
}
76103
});
77104
}
105+
isAutocompleteOpen = true;
78106
});
79107
},
80108
300
81109
);
82110
});
83111

84-
$('#rechercheAdresseListe select').on('keypress', function(e){
85-
var code = e.keyCode || e.which;
86-
if (code == 32 && $('#rechercheAdresseListe').is(':visible')) {
87-
$('#rechercheAdresseListe select option:selected').trigger('click');
88-
}
89-
});
90-
$('#rechercheAdresseListe select').on('change', function(e){
91-
$('#rechercheAdresseListe select option:selected').trigger('click');
112+
113+
$('input#rechercheAdresse').on('keydown', function (event) {
114+
if (event.key === 'ArrowDown') {
115+
event.preventDefault();
116+
handleDown();
117+
} else if (event.key === 'ArrowUp') {
118+
event.preventDefault();
119+
handleUp();
120+
} else if (event.key === 'Enter') {
121+
event.preventDefault();
122+
handleEnter();
123+
} else if (event.key === 'Tab') {
124+
closeSuggestions();
125+
}
92126
});
93127

94128
$('#toggle-skip-search-address').on('click', function(){
@@ -113,4 +147,68 @@ function initSearchAddress() {
113147
$('#adresse_afficher_les_champs button').removeClass('fr-icon-eye-off-line');
114148
}
115149
});
150+
151+
function handleDown() {
152+
const suggestions = $('.fr-autocomplete-suggestion');
153+
if (selectedSuggestionIndex < suggestions.length - 1) {
154+
selectedSuggestionIndex++;
155+
updateSelectedSuggestion();
156+
}
157+
}
158+
159+
function handleUp() {
160+
if (selectedSuggestionIndex > 0) {
161+
selectedSuggestionIndex--;
162+
updateSelectedSuggestion();
163+
}
164+
}
165+
166+
function updateSelectedSuggestion() {
167+
const suggestions = $('.fr-autocomplete-suggestion');
168+
suggestions.each(function(index, suggestion) {
169+
if (index === selectedSuggestionIndex) {
170+
$(suggestion)
171+
.addClass('fr-autocomplete-suggestion-highlighted')
172+
.attr('aria-selected', 'true');
173+
} else {
174+
$(suggestion)
175+
.removeClass('fr-autocomplete-suggestion-highlighted')
176+
.attr('aria-selected', 'false');
177+
}
178+
});
179+
}
180+
181+
function handleEnter() {
182+
const suggestions = $('.fr-autocomplete-suggestion');
183+
if (selectedSuggestionIndex !== -1) {
184+
let formPrefix = ($('#signalement_history_adresse').length > 0)
185+
? 'signalement_history'
186+
: 'signalement_front';
187+
188+
$('#rechercheAdresse').val(suggestions.eq(selectedSuggestionIndex).data('label'));
189+
$('#' + formPrefix + '_adresse').val(suggestions.eq(selectedSuggestionIndex).data('name'));
190+
$('#' + formPrefix + '_codePostal').val(suggestions.eq(selectedSuggestionIndex).data('postcode'));
191+
$('#' + formPrefix + '_ville').val(suggestions.eq(selectedSuggestionIndex).data('city'));
192+
$('#' + formPrefix + '_codeInsee').val(suggestions.eq(selectedSuggestionIndex).data('citycode'));
193+
let geoloc = suggestions.eq(selectedSuggestionIndex).data('geoloclat')
194+
+ '|'
195+
+ suggestions.eq(selectedSuggestionIndex).data('geoloclng');
196+
197+
$('#' + formPrefix + '_geoloc').val(geoloc);
198+
199+
$('#rechercheAdresseListe').hide();
200+
if ($('.address-fields').length > 0) {
201+
$('.address-fields').removeClass('fr-hidden');
202+
$('.skip-search-address').hide();
203+
}
204+
205+
closeSuggestions();
206+
}
207+
}
208+
209+
function closeSuggestions() {
210+
$('.fr-autocomplete-list').html('');
211+
selectedSuggestionIndex = -1;
212+
isAutocompleteOpen = false;
213+
}
116214
}

assets/controllers/form_signalement_front.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ class PunaisesFrontSignalementController {
5959
self = this;
6060
self.fetchTerritoireOpened();
6161
$('input').on('keyup', function(e){
62-
if (e.which == 13) {
62+
// Do not move to the next screen when pressing Enter while selecting an address
63+
if (e.which == 13 && e.currentTarget.id !== 'rechercheAdresse') {
6364
e.preventDefault();
6465
$('#step-'+self.stepStr + ' .btn-next').trigger( "click" );
6566
}

assets/styles/app.scss

+15-11
Original file line numberDiff line numberDiff line change
@@ -195,17 +195,21 @@ span.statut-infestation {
195195
z-index: 1;
196196
display: none;
197197
border: 1px solid;
198-
background: #FFF;
199-
min-width: 300px;
200-
select {
201-
width: 100%;
202-
203-
option {
204-
cursor: pointer;
205-
&:hover {
206-
background-color: #dde5ff;
207-
}
208-
}
198+
background-color: var(--background-alt-blue-france);
199+
min-width: 100%;
200+
list-style-type: none;
201+
202+
.fr-autocomplete-list {
203+
cursor: pointer;
204+
}
205+
.fr-autocomplete-suggestion:hover {
206+
background-color: var(--artwork-minor-blue-cumulus);
207+
color: white !important;
208+
}
209+
210+
.fr-autocomplete-suggestion-highlighted {
211+
background-color: #417dc4;
212+
color: white !important;
209213
}
210214
}
211215
}

templates/front_signalement/_partial_step_info_logement.html.twig

+13-6
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,22 @@
3434
<span class="fr-hint-text help-text">Saisissez le début de votre adresse puis sélectionnez-la dans la liste.</span>
3535
</label>
3636
<div class="fr-input-wrap fr-icon-map-pin-2-line">
37-
<input id="rechercheAdresse" type="text" class="fr-input" autocomplete="street">
37+
<input id="rechercheAdresse"
38+
type="text"
39+
class="fr-input"
40+
autocomplete="street"
41+
aria-controls="rechercheAdresseListe"
42+
aria-autocomplete="list"
43+
role="combobox"
44+
45+
>
3846
<p id="rechercheAdresse-error" class="fr-error-text fr-hidden">
39-
Veuillez renseigner l'adresse de votre logement.
47+
Veuillez renseigner et sélectionner l'adresse de votre logement.
4048
</p>
4149
</div>
42-
<div id="rechercheAdresseListe" class="fr-mt-1v fr-py-1w">
43-
<select size="5">
44-
</select>
45-
</div>
50+
<ul id="rechercheAdresseListe"
51+
class="fr-grid-row fr-background-alt--blue-france fr-text-label--blue-france fr-autocomplete-list">
52+
</ul>
4653
</div>
4754

4855
<div class="fr-toggle">

templates/signalement_create/tab-1.html.twig

+11-5
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,17 @@
2626
</span>
2727
</label>
2828
<div class="fr-input-wrap fr-icon-map-pin-2-line">
29-
<input id="rechercheAdresse" type="text" class="fr-input" autocomplete="street">
30-
<div id="rechercheAdresseListe" class="fr-mt-1v fr-py-1w">
31-
<select size="5">
32-
</select>
33-
</div>
29+
<input id="rechercheAdresse"
30+
type="text"
31+
class="fr-input"
32+
autocomplete="street"
33+
aria-controls="rechercheAdresseListe"
34+
aria-autocomplete="list"
35+
role="combobox"
36+
>
37+
<ul id="rechercheAdresseListe"
38+
class="fr-grid-row fr-background-alt--blue-france fr-text-label--blue-france fr-autocomplete-list">
39+
</ul>
3440
</div>
3541
</div>
3642
</div>

0 commit comments

Comments
 (0)