Balise HTML dialog et fenêtre modale pour Electron

Pour remplacer prompt() ou autre dialogue, une balise HTML simple d'emploi.

La balise <dialog> de HTML n'est à ce jour (avril 2017) implémentée que dans Chrome. Donc non utilisable dans une application Web, mais pour Electron, c'est différent...

Dans un précédent article, nous avons vu comme remplacer la boite de dialogue prompt(), absente sous Electron, par BrowserWindows. Cela fonctionne dans ipcMain, mais ce serait plus simple si on avait une solution dans ipcRenderer, donc directement dans le code de l'interface de l'application. Avec la nouvelle balise <dialog>, on peut justement créer une boite de dialogue modale en HTML.

Celle-ci sera toujours asynchrone dans la mesure ou le traitement ne s'arrête pas au point de création de la boite de dialogue. Mais elle bloque l'interaction avec l'utilisateur jusqu'à ce qu'elle soit fermée, dont elle est modale, ce qui est requis si le traitement dépend de la réponse de l'utilisateur.

Le code source de la boite de dialogue est simple...

<dialog id="pDialog">
<label for="pAnswer" id="pLabel">Default label:</label>
<input id="pAnswer" type="text" value="">
<menu>
<button onclick="pDialog.close('')">Cancel</button>
<button onclick="pDialog.close(document.getElementById('pAnswer').value)">OK</button>
</menu>
</dialog>

La méthode close de dialog retourne une valeur donnée par le programme. Dans le cas présent, quand l'utilisateur clique sur le bouton OK, on retourne ce qu'il a tapé dans le champ d'entrée de texte.

Quand l'utilisateur clique sur le bouton Cancel, une chaîne vide est retournée.

On définit ensuite la fonction qui va remplacer la commande prompt():

function promptDialog(question, cb) {
  var pDialog = document.getElementById('pDialog')

  var fe = function(e) {
    cb(pDialog.returnValue)
    pDialog.removeEventListener("close", fe)
  }  

  document.getElementById("pLabel").innerHTML = question  
  var x = pDialog.showModal()
  pDialog.addEventListener('close', fe)
}

Le premier paramètre est le libellé de la boite, qui correspond à la question à laquelle l'utilisateur doit donner une réponse.
Le second paramètre est un callback, nécessaire parce que dialog est asynchrone, et sert à retourner la réponse.

On ouvre la boite avec la méthode showModal(). Puis la valeur donnée en paramètre à la méthode close() est récupérée grâce à un listener et l'attribut returnValue de dialog.

On utilise ce prompt de remplacement avec un appel de fonction:

promptDialog("Mon propre libellé:", function(x) {
    if(x != '')
        alert(x)
})

Remplacez alert(x) par le code propre à votre application...

Le code complet de la démo est disponible dans une archive:

Pour lancer la démo, tapez: electron dialog.js

Ce code peut être généralisé pour toutes sortes de boites de dialogues et en fait rend dialog.showMessageBox() obsolète.

La boite de dialogue est utilisée par Advanced Explorer depuis la version 4.3 pour les fonctions Copy/rename et Create folder.