lib/widgets/mqVirtualKeyboard/ButtonMq.js

import $ from 'jquery'
import Button from 'src/lib/widgets/mqVirtualKeyboard/Button'
import { j3pIsHtmlElement } from 'src/legacy/core/functions'
import { showMqCursor } from 'src/lib/widgets/mqVirtualKeyboard/MqVirtualKeyboard'

export const dispatchFakeKeyup = (inputMq, options = {}) => {
  // On simule un événement keyup qui ne fait rien, au cas où le champ serait marqué en rouge à la suite d’une erreur (pour retirer cette marque)
  const ke = new KeyboardEvent('keyup', { bubbles: true, ...options })
  // Ci-dessous il faut employer keyup et pas keydown :
  // - en cas d’appui long sur une touche, il peut y avoir répétition du keydown, mais jamais du keyup
  // - les listeners de la plupart des sections j3p écoutent keyup
  ke.isFake = true
  inputMq.dispatchEvent(ke)
}

export const doCharAction = (inputMq, char) => {
  // Un bug MathQuill fait que si, sur PC, on tape très rapidement sur un touche correspondant par
  // exemple à un chiffre très rapidement un curseur fantôme (non clignotant) apparaît.
  // Ce qui suit est un work-around (pas parfait)
  // Sinon il suffirait de faire   $inputMq.mathquill('typedText', char) suivi d’un dispatchFakeKeyup(inputMq)
  showMqCursor(inputMq, false)
  $(inputMq).mathquill('typedText', char)
  showMqCursor(inputMq, true)
  dispatchFakeKeyup(inputMq)
}

class ButtonMq extends Button {
  /**
   * Créé un <button> rattaché à un input mathquill. Avec une value et sans onClick ça crée le onClick qui ajoutera la value dans l’input
   * @param {HTMLSpanElement} inputMq L’input Mathquill (un span.mq-editable-field)
   * @param {ButtonOptions} options
   */
  constructor (inputMq, options = {}) {
    if (typeof window.jQuery.fn.mathquill !== 'function') throw Error('MathQuill n’est pas chargé')
    if (!j3pIsHtmlElement(inputMq) || !inputMq.classList.contains('mq-editable-field')) throw Error('input mathquill invalide')
    const { onClick, value } = options
    // Simule un événement keyup qui ne fait rien, au cas où le champ serait marqué en rouge à la suite d’une erreur (pour retirer cette marque)

    if (onClick) {
      options.onClick = onClick
    } else if (value) {
      // on crée un listener qui ajoute la value dans l’input
      options.onClick = () => doCharAction(inputMq, value)
    }
    super(options)
    this.inputMq = inputMq
  }

  /**
   * Ajoute un bouton dans container
   * @param {HTMLElement} container
   * @param {HTMLSpanElement} inputMq L’input Mathquill (un span.mq-editable-field)
   * @param {ButtonOptions} options
   */
  static addInto (container, inputMq, options) {
    // on est une méthode statique, this fait référence à la classe elle-même
    // ne pas mettre ici ButtonMq mais this permet de faire fonctionner ça pour toutes les classes qui étendent ButtonMq
    const btn = new this(inputMq, options)
    container.appendChild(btn.element)
  }
}

export default ButtonMq