Impossible de sortir de certaines modals avec "Escape"

Contrairement à la v4.3 aux modals en jQuery (?!), il n’est pas possible de fermer les modals « Configuration du plugin » en utilisant la touche « Escape » du clavier.

Reproduit avec le plugin Script :


Le plugin MQTT2 :

Ou encore jMQTT.

De même pour les modals « Notes », « Testeur d’expression », « Variables », « Recherche » :
image

Ou encore la boite de dialogue « A propos ».

Page concernée : Modal « Configuration du plugin » ouverte avec la « clé plate » sur la page d’un plugin.
Ainsi que d’autres modals du Core, cf plus haut.

Version Core : v4.4.0 (alpha commit 2b07237)

Hello,

Quelqu’un s’est penché sur le sujet ?

Merci,
Bad

Hello Bad,

J’ai regardé un peu de mon coté, mais j’arrive pas a trouver ce qui permettait de fermer les modals en 4.3 …

En 4.4, j’ai testé quelques trucs mais pas très propres :grin:

Yop @Phpvarious,

Merci de t’être penché sur ce « bug ».
Pour moi, il faudrait faire un truc du style : intercepter la touche « Escape » quand une modale est ouverte et effectuer l’action liée à la croix, ou alors juste tuer la modale.

Possible ?

Bad

J’ y ai pensé mais l’event clavier se limite au éléments « focusable », sinon faire un addEventListener dans utils.js, mais je sais pas.si cest très propre.

Mais justement, je me pose la question, qui a le focus dans une modale ?
Je ne reproduis pas avec 4.3 le comportement: j’ouvre une modale, par exemple « à propos » et j’appuie sur échap, il ne se passe rien du tout !

Par contre, si je clic dans la modale, alors je peux faire échap et ça la ferme. Elle a donc bien besoin d’avoir le focus. Et pourtant il n’y a aucun bouton de formulaire dans cette popup.

Par ailleurs, si tu fais un « addEventListener » global, il va fermer toutes les popup en même temps je suppose (ça doit peut être pas arriver souvent qu’on superpose des popup)

Oui c’est bien ce comportement que j’ai compris, mais je n’arrive pas a le cibler dans le code du core.
Est-ce un comportement lié a jQuery ?
J’ai testé de capturer un event sur la modale en full js, mais je bute sur le fait que le div n’est pas un element « focusable », et il faut être dans un input par exemple pour déclencher l’évènement.

J’ai testé cette approche qui fait le job, mais je doute de ca propreté :grin: :

dans ce même listener j’ai ajouté :

// Close jeeDialog :    
    if (event.target.matches('body')) {
      if (event.key == 'Escape') { 
        document.querySelectorAll('div.jeeDialog').forEach( _dialog => {
          if (isset(_dialog._jeeDialog)) {
            _dialog._jeeDialog.close(_dialog)
          }
        })
      }
    }

En effet !

Alors là, je ne sais pas comment fait jQuery pour l’intercepter malgré tout…

Ca ne me semble pas si mal que ça !
S’il y avait un moyen de ne close que la modale la plus « haute » ce serait top.
Genre récup toutes les modales et comparer leur « profondeur » dans la page, c’est possible ?

Bad

Je me suis basé sur cette event :

Il nous faudrait un @kiboost pour ca :rofl:

Pour info ,j’ai ouvert 2 modales et elles ont toutes les 2 la classe jeeDialogMain :
image

Et celle sélectionnée a aussi la classe active :slight_smile:

Tu dois pouvoir faire un document.getElementsByClassName('jeeDialog active') et récup la croix dedans ?
Ca me semble être une bonne pise, non ?

Ah oui bien vu, je n’avait pas remarqué que la class active disparaissait lors de l’ouverture d’une seconde modale.

Du coup :

    // Close jeeDialog :    
    if (event.target.matches('body')) {
      if (event.key == 'Escape') {
        document.querySelectorAll('div.jeeDialog.active').forEach( _dialog => {
          if (isset(_dialog._jeeDialog)) {
            _dialog._jeeDialog.close(_dialog)
          }
        })
      }
    }

Permet bien de close la modale qui est active.

Bonjour,
J’ai regardé mais pas simple cette histoire… Une des joie de jquery qui fait tout mais on sait pas trop comment… Si vous avez une solution « propre » (car des solutions sale j’ai mais ca ferme toute les modal…) je suis preneur.

Bonjour Loic,
Dans mon dernier Post, je propose une solution qui permet de close que la modale qui est active. Après a voir si cest propre :grin:

Salut,

J’ai eu l’occasion de tester ce matin, un truc simple qui semble fonctionner comme voulu :

dans desktop/utils.js à la ligne 872 :

  document.body.addEventListener('keydown', function(event) {
    if (event.key == 'Escape') {
      if (event.target.matches('input[id^="in_search"]')) {
        //search input escape:
        event.stopPropagation()
        var els = ((els = document.querySelectorAll('#categoryfilter li .catFilterKey')) != null ? els.forEach(function(item) { item.checked = true }) : null)
        var els = ((els = document.querySelectorAll('#dashTopBar button.dropdown-toggle')) != null ? els.removeClass('warning') : null)
        event.target.value = ''
        return
      }
      else
        //close active modal
        document.querySelector('div.jeeDialog.active')?._jeeDialog.close()
    }
  })

Et j’ai remarqué au passage que la classe active ne revenait pas sur la fenêtre du dessous si plusieurs fenêtres ouvertes donc dans core/dom.ui.js j’ai ajouté ça ligne 1583 dans la fonction close de la modale :

for (var _dialog of document.querySelectorAll('div.jeeDialog.jeeDialogMain')) {
  if (_dialog.isVisible()) {
    _dialog.addClass('active')
    break
  }
}

Des avis là dessus @Phpvarious, @Loic ?

Pour le 1er ca me semble bon pour le 2eme je peux tu peux faire mieux avec un truc du genre

document.querySelectorAll(‹ div.jeeDialog.jeeDialogMain:not([style=« display: none; »]) ›)[0]?.addClass(‹ active ›)

A tester quand meme je suis pas encore bien habitué au vanilla js.

Effectivement pour remettre une éventuelle autre fenêtre ouverte active ceci semble fonctionner :

document.querySelectorAll('div.jeeDialog.jeeDialogMain:not([style*="display: none;"])')[0]?.addClass('active')

Je vais commit ces 2 modifs, ça pourra toujours être affiné à l’avenir en fonction des retours.

Hello,

C’est pas mal tous ca :+1:

en faite dans mon test j’avais rajouté la condition event.target.matches('body') ce qui permettait de ne pas close la modal si l’event intervient dans un input par exemple.

:+1: seul petite remarque :grin:, c’est qu’il n’y a pas de notion de « profondeur », si 3 modales d’ouverte, et que je close la 3ème, cela active la 1ère.

Je sais pas si c’est propre, mais j’ai testé ceci :

var _dialog = document.querySelectorAll('div.jeeDialog.jeeDialogMain:not([style*="display: none;"])')
_dialog[_dialog.length- 1]?.addClass('active')

J’ai tenté avec un :last-child mais sans succès.

Ce sujet a été automatiquement fermé après 24 heures suivant le dernier commentaire. Aucune réponse n’est permise dorénavant.