/** @module loadMathquill */
/* global MathQuill */
let loadedPromise = null
// pour un rendu auto au chargement cf les versions de ce fichier avant 2020-04-10 (fct renderAll)
/**
* Charge jQuery et les css mathquill en parallèle, met jQuery en global puis charge mathquill
* @return {Promise}
*/
export default async function loadMathquill () {
// si on est appelé plusieurs fois on ne relance pas le chargement
if (loadedPromise) return loadedPromise
// on lance ça en parallèle, mais juste après le js
let parallelCssLoadingPromise
setTimeout(() => {
parallelCssLoadingPromise = Promise.all([
import('./surcharge.scss'),
import('../../vendors/mathquill/0.10.1/mathquill.css')
])
}, 0)
const { default: jQuery } = await import('jquery')
// mathquill veut un jQuery en global
window.jQuery = jQuery
await import('../../vendors/mathquill/0.10.1/mathquill.js')
// ici on pourrait ajouter une config, cf http://docs.mathquill.com/en/latest/Config/
// on recrée l’ancien $.mathquill() d’après le code de legacy/externals/mathquill/mathquill_maj.js
// https://github.com/mathquill/mathquill/wiki/v0.9.x-%E2%86%92-v0.10.0-Migration-Guide
window.jQuery.fn.mathquill = function mathquill (cmd, latex) {
const $elt = this // élément jQueryfié sur lequel on est appelé
// console.log('** mathquill avec les arguments', arguments, 'sur', $elt)
const MQ = MathQuill.getInterface(2)
// appel de $(…).mathquill()
if (arguments.length === 0) return MQ.MathField($elt[0])
const hasMultipleArguments = arguments.length > 1
if (arguments.length > 1 && typeof latex !== 'string') {
if (typeof latex === 'number') {
console.warn(Error(`Appel invalide de mathquill('${cmd}', latex) où latex est un number (il a été converti en string mais devrait l’être avant l’appel)`))
latex = String(latex)
} else {
return console.error(Error(`Appel invalide de mathquill('${cmd}', latex) où latex n’est pas une string (${typeof latex})`))
}
}
// y’a des arguments, et si latex est fourni c’est une string, et on fait ces modifs,
// cf breaking changes de https://github.com/mathquill/mathquill/wiki/v0.9.x-%E2%86%92-v0.10.0-Migration-Guide
if (latex) latex = latex.replace(/\\a((?:sin|cos|tan|sec|csc|cosec|cot|cotan)h?)\b/g, '\\arc$1')
// reste à gérer la migration de ces commandes d’après
// https://github.com/mathquill/mathquill/wiki/v0.9.x-%E2%86%92-v0.10.0-Migration-Guide
const mathField = MQ.MathField($elt[0])
if (!mathField) {
console.error(Error('Aucun champ math trouvé dans'), $elt)
return $elt
}
switch (cmd) {
case 'cmd':
// http://docs.mathquill.com/en/latest/Api_Methods/#cmdlatex_string
// if (latex) $elt.cmd(latex)
if (latex) mathField.cmd(latex)
else console.error(Error('appel de matquill("cmd") sans 2e argument'))
return $elt
case 'editable':
return mathField
case 'latex': {
// http://docs.mathquill.com/en/latest/Api_Methods/#latex
// pas sûr que lui passer undefined revienne à ne pas lui passer d’argument (on sait pas s’il regarde arguments.length)
// dans le doute on distingue
if (hasMultipleArguments) {
// deux arguments, on affecte
mathField.latex(latex)
// et on retourne l’élément pour pouvoir chaîner
return $elt
}
// un seul argument, on veut récupérer le contenu et on le retourne
const isEditable = $elt.hasClass('mq-editable-field')
const res = mathField.latex() // cette commande ajoute la classe mq-editable-field
// donc faut la virer si elle n’y était pas avant
if (!isEditable) $elt.removeClass('mq-editable-field')
return res
}
case 'focus':
mathField.focus()
return $elt
case 'blur':
mathField.blur()
return $elt
case 'redraw':
// http://docs.mathquill.com/en/latest/Api_Methods/#reflow
mathField.reflow()
return $elt
case 'revert':
// http://docs.mathquill.com/en/latest/Api_Methods/#revert
// Problème avec certaines sections de Rémi. Je mets un try catch en attendant
// mathField.revert()
$elt.removeClass('mq-editable-field')
return $elt
case 'write':
if (latex) mathField.write(latex)
else console.error(Error('appel de matquill("write") sans 2e argument'))
return $elt
case 'typedText' :
if (latex) mathField.typedText(latex)
else console.error(Error('appel de matquill("typedText") sans 2e argument'))
return $elt
case 'keystroke' :
if (latex) mathField.keystroke(latex)
else console.error(Error('appel de matquill("keystroke") sans 2e argument'))
return $elt
default:
console.warn(`Commande mathquill ${cmd} non implémentée`)
return $elt
}
}
// On redéfinit la $.focus pour que, si elle est appelée sur un champ editable
// elle utilise notre code (et sinon l’original)
const oldFocus = window.jQuery.fn.focus
window.jQuery.fn.focus = function focusMod () {
const $elt = this
if ($elt.hasClass('mq-editable-field')) {
const MQ = MathQuill.getInterface(2)
const mathField = MQ.MathField($elt[0])
mathField.focus()
return $elt
}
// c’est pas un champ éditable, on applique l’original
return oldFocus.apply(this, arguments)
}
// on résoud l’ensemble quand les css sont complètement chargées
await parallelCssLoadingPromise
// on stocke une promesse résolue pour les éventuels appels suivants
loadedPromise = Promise.resolve()
} // loadMathquill