@@ -110,6 +110,13 @@ class SearchEngineAdvanced extends Control {
110110 */
111111 this . _searchForms ;
112112
113+ /**
114+ * Si vrai, écoute les clics sur le document pour gérer
115+ * la modale de recherche avancée
116+ * @type {Boolean }
117+ */
118+ this . listenToClick = false ;
119+
113120 if ( options . advancedSearch && options . advancedSearch instanceof Array ) {
114121 this . _searchForms = options . advancedSearch ;
115122 } else {
@@ -193,6 +200,16 @@ class SearchEngineAdvanced extends Control {
193200 } . bind ( this ) ) ;
194201
195202 this . on ( "search" , this . addResultToMap . bind ( this ) ) ;
203+
204+ // Gère le cas du conteneur de recherche avancée
205+ [ "mousedown" , "focusin" ] . map ( eventListener => document . addEventListener ( eventListener , this . _onDocumentClick . bind ( this ) ) ) ;
206+
207+ this . advancedBtn . addEventListener ( "blur" , function ( e ) {
208+ if ( e . relatedTarget === this . baseSearchEngine . input ) {
209+ this . listenToClick = false ;
210+ this . advancedBtn . setAttribute ( "aria-expanded" , false ) ;
211+ }
212+ } . bind ( this ) ) ;
196213 }
197214
198215 /**
@@ -314,12 +331,27 @@ class SearchEngineAdvanced extends Control {
314331
315332 // Gestion du bouton avancé
316333 advancedBtn . setAttribute ( "aria-controls" , advancedContainer . id ) ;
317- advancedBtn . addEventListener ( "click" , ( e ) => {
334+ advancedBtn . addEventListener ( "click" , function ( /** @type { PointerEvent } */ e ) {
318335 e . preventDefault ( ) ;
319336 const isHidden = advancedBtn . getAttribute ( "aria-expanded" ) === "false" ;
320337 advancedBtn . setAttribute ( "aria-expanded" , isHidden ) ;
321- this . baseSearchEngine . setActive ( isHidden ) ;
322- } ) ;
338+ this . listenToClick = isHidden ;
339+ if ( isHidden ) {
340+ // Si la modale est ouverte, on met le focus sur le premier élément focusable
341+ const focusableSelectors = [
342+ "a[href]" ,
343+ "button:not([disabled])" ,
344+ "input:not([disabled])" ,
345+ "select:not([disabled])" ,
346+ "textarea:not([disabled])" ,
347+ "[tabindex]:not([tabindex='-1'])"
348+ ] . join ( "," ) ;
349+ const firstFocusable = advancedContainer . querySelector ( focusableSelectors ) ;
350+ if ( firstFocusable ) {
351+ firstFocusable . focus ( ) ;
352+ }
353+ }
354+ } . bind ( this ) ) ;
323355
324356 // N'ajoute pas le bouton s'il n'y a pas d'options avancées
325357 if ( this . _searchForms . length ) {
@@ -343,6 +375,24 @@ class SearchEngineAdvanced extends Control {
343375 this . baseSearchEngine . optionscontainer . appendChild ( eraseBtn ) ;
344376 }
345377
378+ /**
379+ * Fonction active si la recherche avancée est active
380+ * @param {PointerEvent } e Événement de clic sur le document
381+ */
382+ _onDocumentClick ( e ) {
383+ if ( this . listenToClick === true ) {
384+ // Écoute des clics sur le document ==> recherche avancée active
385+ const clickOnAdvancedContainer = ( this . advancedContainer === e . target || this . advancedContainer . contains ( e . target ) ) ;
386+ const clickOnAdvancedBtn = this . advancedBtn === e . target ;
387+ if ( ! ( clickOnAdvancedContainer || clickOnAdvancedBtn ) ) {
388+ // On fait une action si un clic se produit en dehors du conteneur
389+ // Et si le bouton de recherche avancée n'est pas cliqué
390+ this . listenToClick = false ;
391+ this . advancedBtn . setAttribute ( "aria-expanded" , false ) ;
392+ }
393+ }
394+ }
395+
346396 /**
347397 * Ajoute les résultats (features) sur la carte et ajuste la vue.
348398 * @param {Object } e Événement de recherche contenant result/extent
0 commit comments