/*
* Created by yvesb on 19/10/2016.
*/
/*
* MathGraph32 Javascript : Software for animating online dynamic mathematics figures
* https://www.mathgraph32.org/
* @Author Yves Biton (yves.biton@sesamath.net)
* @License: GNU AGPLv3 https://www.gnu.org/licenses/agpl-3.0.html
*/
import { ce, getStr, preventDefault } from '../kernel/kernel'
import $ from 'jquery'
/**
* L'id du div utilisé pour les boîtes de dialogue (utilisé en dur dans le code dans beaucoup de sélecteurs)
* @type {string}
*/
export const idDivDlg = 'divMtgDlg'
export default MtgDlg
/**
* Constructeur de la boîte de dialogue
* @param {MtgApp} app L'application propriétaire
* @param {string} id L'id de la fenêtre
* @param {VoidCallback} callBackOK null ou fonction de callBack à appeler après OK
* @param {VoidCallback} callBackCancel null ou fonction de callBack à appeler après annulation
* @constructor
*/
function MtgDlg (app, id, callBackOK = null, callBackCancel = null) {
if (arguments.length > 0) {
if (!app.divDlg) throw Error('Cette instance n’a pas de divDlg et ne peut pas gérer de boites de dialogue')
this.app = app
this.id = id
this.callBackOK = callBackOK
this.callBackCancel = callBackCancel
// this.timeStart = new Date(); // Est maintenant dans onOpen
// Version 6.9.3 : Il ne faut pas considérer les CarSpeciauxDlg comme des dialogue à part entière
// car ce sont toujours des enfants d'uen autre dialogue.
// Dans cette modif, dans EntreeNomDlg si on appuie très rapidemnt sur OK plusieurs fois de suite
// ça finit par planter car en cas d'affichage d'une AvertDlg, le charSpeciauxDlg peut être le dernier créé
// et la sécurité pour ne pas afficher le même AvertDlg ne fonctionne plus
// app.dlg.push(id)
if (id !== 'charspedlg') app.dlg.push(id)
this.dlgCharSpe = null // Utilisé par les MtgInputWithCharSpe et CarSpeciauxDlg
try { // Try nécessaire à cause de l'averstissement qui peut apparaître si on veut ouvrir sous electron un fichier invalide
app.cacheTip()
} catch (e) {
console.error(e)
}
this.div = ce('div', {
id
})
$(this.div).css('-webkit-tap-highlight-color', 'transparent') // Pour éviter le grisé sur ipad
this.parentDiv = app.divDlg
this.parentDiv.appendChild(this.div)
}
}
MtgDlg.prototype.appendChild = function (el) {
this.div.appendChild(el)
}
// Délai au-dessous duquel on ne répond pas aux boutons de validation ou d'annulation (en ms)
// MtgDlg.delay = 1000;
MtgDlg.prototype.stopEvent = function (evt) {
preventDefault(evt)
evt.stopPropagation()
}
/**
* Fonction créant la boîte de dialogue avec un titre title et une largeur width
*/
/**
* Fonction pouvant être appelée pour construire la boîte de dialogue
* quand this.OK() doit être appelé quand on clique sur OK et rien ne doit être fait
* si on annule ou referme la boîte de dialogue.
* @param {string} title Le titre de la boîte de dialogue
* @param width La largeur de la boîte de dialogue
* ou ferme la fenêtre
*/
MtgDlg.prototype.create = function (title, width) {
const self = this
/*
var buttons = {} ;
buttons[getStr("OK")] = function(ev){
self.OK(ev);
self.stopEvent(ev)
};
buttons[getStr("Cancel")] = function(ev){
self.onCancel(ev);
self.stopEvent(ev);
} ;
*/
const buttons = [
{
text: getStr('OK'),
id: 'btnOK',
click: function (ev) {
self.stopEvent(ev) // Déplacé version 6.9.3
self.OK() // paramètre ev supprimé version 6.9.3 car ne sert jamais
}
},
{
text: getStr('Cancel'),
id: 'btnCancel',
click: function (ev) {
self.stopEvent(ev) // Déplacé version 6.9.3
self.onCancel() // paramètre ev supprimé version 6.9.3 car ne sert jamais
}
}
]
$('#' + self.id).dialog({
modal: true,
title: getStr(title),
buttons,
close: function (ev) {
self.stopEvent(ev)
self.onClose()
},
open: function () {
self.onOpen()
},
width,
closeOnEscape: false,
// On centre la boîte de dialogue sur le div parent de l'application
position: { my: 'center', at: 'center', of: `#${idDivDlg}` }
})
}
/**
* Fonction appelée par défaut lorsque l'utilisateur appuie sur le bouton annuler
* Par défaut cette fonction retourne si un certaint temps ne s'est pas écoulé entre l'affichage de la fenêtre et le
* clic sur le bouton Annuler, ferme la fenêtre et réactive l'outil actif
* Pour un comportement autre que ce comportement standard, reédinir cette fonction (sans appeller la méthode ancêtre)
*/
MtgDlg.prototype.onCancel = function () {
if (this.callBackCancel !== null) this.callBackCancel()
this.destroy()
}
/**
* Fonction appelée par défaut lorsque l'utilisateur referme la boîte
* Par défaut cette fonction retourne si un certaint temps ne s'est pas écoulé entre l'affichage de la fenêtre et le
* clic sur le bouton Annuler, ferme la fenêtre et réactive l'outil actif
* Pour un comportement autre que ce comportement standard, reédinir cette fonction (sans appeller la méthode ancêtre)
*/
MtgDlg.prototype.onClose = function () {
if (this.callBackCancel !== null) this.callBackCancel()
this.destroy()
}
/**
* Fonction appelée à l'ouverture de la fenêtre.
* A appeler par les fonctions rédéfinissant cette fonction
*/
MtgDlg.prototype.onOpen = function () {
this.app.effaceIndication()
$('#btnOK').focus()
}
MtgDlg.prototype.destroy = function () {
if (this.dlgCharSpe !== null) {
this.dlgCharSpe.destroy()
this.dlgCharSpe = null
}
$('#' + this.id).dialog('destroy')
// this.app.dlg.pop() // Modifié version 6.9.3
if (this.id !== 'charspedlg') this.app.dlg.pop()
// Une fois le dialogue détruit, le div qui a servi à le générer est de nouveau présent. Il faut le détruire.
this.parentDiv.removeChild(this.div)
// Si un éditeur de nom est en cours on lui redonne le focus
const ne = this.app.nameEditor
if (ne.isVisible) ne.editeur.focus() // Pour que, par défaut, le bouton OK ait le focus
// On retourne en haut de la page (important pour périphériques mobiles)
// $('html,body').scrollTop(0);
}
/* Supprimé version 6.9.3 car pas utilisé
MtgDlg.prototype.tab = function () {
return ce('table', {
cellspacing: 10
})
}
*/