legacy/outils/zoneStyleMathquill/ZoneStyleMathquill3.js

import $ from 'jquery'

import { j3pDetruit, j3pFreezeElt, j3pStyle } from 'src/legacy/core/functions'
import ZoneStyleMathquillBase from 'src/legacy/outils/zoneStyleMathquill/ZoneStyleMathquillBase'
import { notify } from 'sesajs/error'
import { j3pAffiche } from 'src/lib/mathquill/functions'
import { addTable, getCells } from 'src/legacy/themes/table'

import { barreZone } from './functions'
import { blurAllTabs, removeTab, prevTabFocus } from './listeTabulations'

// et notre css
import './zoneStyleMathquill.scss'

class ZoneStyleMathquill3 extends ZoneStyleMathquillBase {
  /**
   *
   * @param {HTMLElement} conteneur
   * @param {Object} parametres
   * @param {string} [parametres.contenu] Contenu éventuel à mettre dans l’input au départ
   * @param {string} [parametres.bloqueFraction]
   * @param {string} [parametres.restric=0123456789.,*+-/²()]
   * @param {string} [parametres.glissefrac=x]
   * @param {string} [parametres.obligecar='']
   * @param {string} [parametres.clavier] idem restric si non fourni, ne doit pas contenir de caractères qui ne seraient pas dans restric (mais on peut en avoir moins si on accepte deux caractères avec le même sens, par ex , et .)
   * @param {number} [parametres.limite]
   * @param {boolean} [parametres.hasAutoKeyboard]
   * @param {string} [parametres.bloqueracine]
   * @param {boolean} [parametres.inverse]
   * @param {function} [parametres.enter] Une callback a appeler sur la touche entrée
   */
  constructor (conteneur, parametres) {
    // on doit toujours commencer par appeler le constructeur de la classe parente
    super(conteneur, { ...parametres, version: 3 })
    // ce qui suit est spécifique à zsm3
    this.type = 'zsm3'
    this.sansBord = Boolean(parametres.sansBord)
    this.petiteFont = Boolean(parametres.petiteFont)
    this.onchange = parametres.onchange
    this.conteneur = conteneur
    this.bloquefrac = parametres.bloqueFraction || ''
    this.restric = this.restric.replace('^', '')
    this.restric = this.restric.replace('$', '')
    if (this.restric.includes('*')) this.restric += '×'
    this.glissefrac = parametres.glissefrac || 'x'
    // pour savoir s’il faut un bouton maj on regarde si y’a des minuscules ET des majuscules
    const yamin = /[a-z]/.test(this.restric)
    const yamaj = /[A-Z]/.test(this.restric)
    this._fautMaj = yamin && yamaj
    this.isCapsLocked = !yamin

    this._isClavierVisible = false

    this.obligecar = parametres.obligecar || ''
    this.hasAutoKeyboard = parametres.hasAutoKeyboard
    this.bloqueracine = parametres.bloqueracine || ''
    this._isLocked = false

    // nos listeners
    this.blok = true
    this._clavierListener = this.clavier.bind(this)
    this._clickcListener = this.clickc.bind(this)
    this._onClickClavier = this.clickKlav.bind(this)
    this._clickZoneListener = this.clickzone.bind(this)
    this._gereBlurListener = this.gereblur.bind(this)
    this._metCurseurListener = this.metcurseur.bind(this)
    this._placeListener = this.place.bind(this, false)
    this._vireListener = this.vire.bind(this)

    /// crea de la zone
    this.texta = conteneur
    // 0 pour simple  1 pour frac
    this.texta.type = 0
    this.texta.poscurseur = 0
    // 0 si dans num , 1 si dans den (pour pos2
    this.texta.elemnum = []
    this.texta.poscurseurIn = false
    this.isBarred = false

    this.constuctorFinalize(parametres.contenu)
    setTimeout(() => { this.blok = false }, 100)
  } // ZoneStyleMathquill3

  barre () {
    this.historique.push('barre')
    this.isBarred = true
    return barreZone(this.textaCont)
  }

  blur () {
    if (this.disabled) return
    if (this._isLocked) return
    this.historique.push('blur')
    this.isblur = true
    this.blurHelper()
    this.texta.poscurseurIn = false
    this.texta.poscurseur = 0
    this.texta.poscurseurInRac = false
  }

  buildKeyboard (useExisting) {
    this.historique.push('buildKeyboard')
    const avirer = this.isCapsLocked ? /[a-z]/g : /[A-Z]/g
    const touches = this.clavierR.replace(avirer, '')
    this.buildKeyboardHelper(touches, { useExisting })
    if (useExisting) this.place(true)
  }

  cacheKlavier () {
    this.historique.push('cacheKlavier')
    const node = this.divClavier
    node.style.visibility = 'hidden'
    node.style.height = '0'
  }

  /**
   * Reconstruit le clavier en invertissant min/maj
   */
  capsLock () {
    this.historique.push('capsLock')
    this.isCapsLocked = !this.isCapsLocked
    this.buildKeyboard(true)
  }

  clavier (event) {
    this.historique.push('clavier', event)
    if (this.disabled ||
      event.code === 'Tab' ||
      event.code === 'Enter' ||
      event.code === 'NumpadEnter'
    ) {
      if (event.code === 'Enter' ||
        event.code === 'NumpadEnter'
      ) {
        event.preventDefault()
        event.stopPropagation()
        if (this.enter) this.enter()
      }
      if (event.key === 'Tab' || event.code === 'Tab') {
        this.blur()
        event.preventDefault()
        event.stopPropagation()
        prevTabFocus(this)
      }
      return
    }
    // pourquoi on désactive la propagation ?
    event.preventDefault()
    event.stopPropagation()

    let muo = event.key
    if (muo === 'Digit0') muo = '0'
    if (muo === '.') muo = ','
    const monres = this.restric

    if ((monres.includes(muo))) {
      if (this.bloquefrac !== undefined) {
        if ((this.bloquefrac.includes(muo)) && (this.texta.poscurseurIn)) {
          this.texta.poscurseurIn = false
          this.texta.poscurseur++
          if (muo === '*') { muo = '×' }
          this.majaffiche(muo)
          return
        }
      }
      if (muo === '*') { muo = '×' }
      this.majaffiche(muo)
    }

    const elemCurseur = this.texta.elemnum[this.texta.poscurseur]
    if (event.code === 'ArrowRight') {
      if (this.texta.poscurseurIn) {
        if (this.texta.poscurseurup) {
          if (elemCurseur[0].length <= this.texta.poscurseur2) {
            this.texta.poscurseurIn = false
            this.texta.poscurseur++
          } else {
            this.texta.poscurseur2++
          }
          this.majaffiche('')
        } else {
          if (elemCurseur[1].length <= this.texta.poscurseur2) {
            this.texta.poscurseurIn = false
            this.texta.poscurseur++
          } else {
            this.texta.poscurseur2++
          }
          this.majaffiche('')
        }
      } else if (this.texta.poscurseurInRac) {
        if (elemCurseur.cont.length <= this.texta.poscurseur2) {
          this.texta.poscurseurInRac = false
          this.texta.poscurseur++
        } else {
          this.texta.poscurseur2++
        }
        this.majaffiche('')
      } else {
        if (this.texta.poscurseur < this.texta.elemnum.length) {
          if (Array.isArray(elemCurseur)) {
            this.texta.poscurseur--
            this.texta.poscurseur2 = 0
            this.texta.poscurseurup = true
            this.texta.poscurseurIn = true
          } else if (elemCurseur?.racine === true) {
            this.texta.poscurseurInRac = true
            this.texta.poscurseur--
            this.texta.poscurseur2 = 0
          } else {
            if ((elemCurseur?.length > 1)) {
              this.texta.elemnum[this.texta.poscurseur] = elemCurseur.substring(0, 1)
              this.texta.elemnum.splice(this.texta.poscurseur + 1, 0, elemCurseur.substring(1, elemCurseur.length))
            }
          }
          this.texta.poscurseur++
          this.majaffiche('')
        }
      }
    }
    if (event.code === 'ArrowLeft') {
      if (this.texta.poscurseurIn) {
        if (this.texta.poscurseurup) {
          if (this.texta.poscurseur2 === 0) {
            this.texta.poscurseurIn = false
          } else {
            this.texta.poscurseur2--
          }
          this.majaffiche('')
        } else {
          if (this.texta.poscurseur2 === 0) {
            this.texta.poscurseurIn = false
          } else {
            this.texta.poscurseur2--
          }
          this.majaffiche('')
        }
      } else if (this.texta.poscurseurInRac) {
        if (this.texta.poscurseur2 === 0) {
          this.texta.poscurseurInRac = false
        } else {
          this.texta.poscurseur2--
        }
        this.majaffiche('')
      } else {
        if (this.texta.poscurseur > 0) {
          const elemCurseur = this.texta.elemnum[this.texta.poscurseur - 1]
          if (Array.isArray(elemCurseur)) {
            this.texta.poscurseur2 = elemCurseur[0].length
            this.texta.poscurseurup = true
            this.texta.poscurseurIn = true
          } else if (elemCurseur?.racine === true) {
            this.texta.poscurseurInRac = true
            this.texta.poscurseur2 = elemCurseur.cont.length
          } else {
            if ((elemCurseur.length > 1)) {
              // faut le remplacer
              this.texta.elemnum[this.texta.poscurseur - 1] = elemCurseur.substring(0, elemCurseur.length - 1)
              this.texta.elemnum.splice(this.texta.poscurseur, 0, elemCurseur.substring(elemCurseur.length - 1, elemCurseur.length))
              this.texta.poscurseur++
            }
          }
          this.texta.poscurseur--
          this.majaffiche('')
        }
      }
    }
    if (event.code === 'ArrowDown') {
      if (this.texta.poscurseurIn) {
        if (this.texta.poscurseurup) {
          this.texta.poscurseurup = false
          this.texta.poscurseur2 = Math.min(elemCurseur[1].length, this.texta.poscurseur2)
          this.majaffiche('')
        }
      }
    }
    if (event.code === 'ArrowUp') {
      if (this.texta.poscurseurIn) {
        if (!this.texta.poscurseurup) {
          this.texta.poscurseurup = true
          this.texta.poscurseur2 = Math.min(elemCurseur[0].length, this.texta.poscurseur2)
          this.majaffiche('')
        }
      }
    }
    if (event.code === 'Backspace') {
      if (this.texta.poscurseurIn) {
        if (this.texta.poscurseur2 === 0) {
          if ((elemCurseur[0].length === 0) && (elemCurseur[1].length === 0)) {
            this.texta.poscurseurIn = false
            this.texta.poscurseur++
            this.clavier({ code: 'Backspace', preventDefault: function () {}, stopPropagation: function () {} })
          }
          return
        }
        if (this.texta.poscurseurup) {
          this.texta.elemnum[this.texta.poscurseur][0].splice((this.texta.poscurseur2 - 1), 1)
        } else {
          elemCurseur[1].splice((this.texta.poscurseur2 - 1), 1)
          // pas besoin de réaffecter, c’est dynamique
        }
        this.texta.poscurseur2--
      } else if (this.texta.poscurseurInRac) {
        if (this.texta.poscurseur2 === 0) {
          this.gereracine()
          return
        }
        elemCurseur.cont.splice((this.texta.poscurseur2 - 1), 1)
        this.texta.poscurseur2--
      } else {
        if (this.texta.poscurseur > 0) {
          if (this.obligecar.includes(this.texta.elemnum[this.texta.poscurseur - 1])) {
            const eLemCoNt = this.textaCont
            // on le passe sur fond rouge
            eLemCoNt.style.backgroundColor = '#ff0000'
            // et on le remettra en blanc dans 100ms
            setTimeout(() => { eLemCoNt.style.backgroundColor = '#ffffff' }, 100)
            return
          }
          this.texta.elemnum.splice((this.texta.poscurseur - 1), 1)
          this.texta.poscurseur--
        }
      }
      this.majaffiche('')
    }
    if (event.code === 'Delete') {
      if (this.texta.poscurseurIn) {
        if (this.texta.poscurseurup) {
          if (this.texta.poscurseur2 === elemCurseur[0].length) return
          elemCurseur[0].splice((this.texta.poscurseur2), 1)
        } else {
          if (this.texta.poscurseur2 === elemCurseur[1].length) return
          elemCurseur[1].splice((this.texta.poscurseur2), 1)
        }
      } else if (this.texta.poscurseurInRac) {
        if (this.texta.poscurseur2 === elemCurseur.cont.length) return
        elemCurseur.cont.splice((this.texta.poscurseur2), 1)
      } else {
        if (this.texta.elemnum.length > this.texta.poscurseur) {
          if (this.obligecar.includes(elemCurseur)) {
            const eLemCoNt = this.textaCont
            // on le passe sur fond rouge
            eLemCoNt.style.backgroundColor = '#ff0000'
            // et on le remettra en blanc dans 100ms
            setTimeout(() => { eLemCoNt.style.backgroundColor = '#ffffff' }, 100)
            return
          }
          this.texta.elemnum.splice(this.texta.poscurseur, 1)
        }
      }
      this.majaffiche('')
    }
  }

  clickc (event) {
    this.historique.push('clickc', event)

    if (this.disabled) { return }
    // e.preventDefault()
    // e.stopPropagation()
    if (event.currentTarget.tab === true) {
      this.texta.poscurseurIn = true
      const popos = event.currentTarget.getBoundingClientRect()
      if (event.clientX > popos.x + popos.width / 2) {
        this.texta.poscurseur2 = event.currentTarget.num3 + 1
      } else {
        this.texta.poscurseur2 = event.currentTarget.num3
      }
      this.texta.poscurseur = event.currentTarget.num
      this.texta.poscurseurup = event.currentTarget.tabnum
      this.texta.poscurseurInRac = false
    } else if (event.currentTarget.rac === true) {
      this.texta.poscurseurInRac = true
      this.texta.poscurseurIn = false
      this.texta.poscurseur = event.currentTarget.num
      this.texta.poscurseur2 = event.currentTarget.num3
    } else {
      const popos = event.currentTarget.getBoundingClientRect()
      if (event.clientX > popos.x + popos.width / 2) {
        this.texta.poscurseur = event.currentTarget.num + 1
      } else {
        this.texta.poscurseur = event.currentTarget.num
      }
      this.texta.poscurseurIn = false
      this.texta.poscurseurInRac = false
    }
    this.unTAbc[0][(event.currentTarget.num + 1) * 2].focus()
  }

  clickKlav (event) {
    this.historique.push('clickKlav', event)

    this._isLocked = true
    setTimeout(() => {
      this._isLocked = false
      this.majaffiche('')
    }, 20)
    const add = event.currentTarget.mes
    if (add === 'MAJ') {
      this.capsLock()
      return
    }
    const e = { key: add, code: add, stopPropagation: function () {}, preventDefault: function () {} }
    this.clavier(e)
  }

  clickzone () {
    this.historique.push('clickzone')

    if (this.disabled) return
    this.isblur = false
    this.textaCont.setAttribute('class', 'zsmMqFocused')
    this.majaffiche('')
  }

  corrige (bon) {
    super.corrige(bon)
    this.historique.push('corrige', bon)
  }

  disable () {
    this.historique.push('disable')

    if (this.disabled) { return }
    this.isblur = true
    removeTab(this)
    this.majaffiche('')
    document.removeEventListener('click', this._gereBlurListener, false)
    this.disabled = true
    this.textaCont.setAttribute('class', '')
    if (this.isBarred) barreZone(this.textaCont)
    for (const i of this.texta.elemnum.keys()) {
      j3pFreezeElt(this.unTAbc[0][i * 2 + 1])
    }
    this.textaCont.removeEventListener('click', this.clickzone, false)

    j3pDetruit(this.textaIm)
    this.cacheKlavier()
    j3pDetruit(this.divClavier)
    if (this.divClavierAuto !== undefined) j3pDetruit(this.divClavierAuto)
  }

  focus () {
    this.historique.push('focus')

    if (this.disabled) { return }
    blurAllTabs(this)
    this.isblur = false
    this.majaffiche('')
    this.textaIm.style.display = ''
  }

  gereblur (event) {
    this.historique.push('gereblur', event)

    if (!$(event.target).closest('#' + this.textaCont.id).length) {
      this.blur()
    }
  }

  gerediv () {
    this.historique.push('gerediv')

    // on cherche ou on est
    let fo = false
    let i1
    let i2
    const t = []
    if (this.texta.poscurseurInRac && this.bloqueracine.includes('/')) return
    if (this.texta.poscurseurIn) {
      const elemCurseur = this.texta.elemnum[this.texta.poscurseur]
      for (let i = 0; i < elemCurseur[0].length; i++) {
        t.push(elemCurseur[0][i])
      }
      this.texta.elemnum.splice(this.texta.poscurseur, 1)
      for (let i = t.length - 1; i > -1; i--) {
        this.texta.elemnum.splice(this.texta.poscurseur, 0, t[i])
      }
      this.texta.poscurseurIn = false
      this.majaffiche('')
    } else {
      if (this.texta.poscurseur > 0) {
        let zu = true
        i1 = this.texta.poscurseur - 1
        i2 = i1
        const elem = this.texta.elemnum[i1]
        if (!Array.isArray(elem)) {
          if (((this.bloquefrac.indexOf(elem) === -1)) && (!(typeof elem === 'object'))) {
            let passort = true
            this.spe = false
            while ((i2 > 0) && passort) {
              if ((!Array.isArray(this.texta.elemnum[i2 - 1])) && ('0123456789.,'.includes(this.texta.elemnum[i2 - 1]))) {
                i2--
              } else {
                passort = false
              }
            }
            for (let i = i1; i > i2 - 1; i--) {
              t.splice(0, 0, this.texta.elemnum[i])
              this.texta.elemnum.splice(i, 1)
            }
            this.texta.elemnum.splice(i2, 0, [t, []])
            zu = false
          } else {
            if (this.glissefrac.includes(elem)) {
              this.texta.poscurseur--
              this.spe = true
              this.gerediv()
              return
            }
            if (this.spe === true) {
              this.spe = false
              this.majaffiche('1')
              this.texta.poscurseur++
              this.gerediv()
              return
            }
            i2++
            this.texta.elemnum.splice(i2, 0, [[], []])
          }
          this.texta.poscurseurIn = true
          this.texta.poscurseur2 = 0
          this.texta.poscurseurup = zu
          this.texta.poscurseur = i2
          this.majaffiche('')
        } else {
          fo = true
        }
      } else {
        if (this.spe === true) {
          this.spe = false
          this.majaffiche('1')
          this.texta.poscurseur++
          this.gerediv()
          return
        }
        fo = true
      }
      if (fo) {
        this.texta.elemnum.splice(this.texta.poscurseur, 0, [[], []])
        this.texta.poscurseurIn = true
        this.texta.poscurseur2 = 0
        this.texta.poscurseurup = true
        this.majaffiche('')
      }
    }
  }

  gereracine () {
    // on cherche ou on est
    this.historique.push('gereracine')

    if (this.texta.poscurseurInRac) {
      const acolle = this.texta.elemnum[this.texta.poscurseur].cont
      this.texta.elemnum.splice(this.texta.poscurseur, 1)
      for (let i = acolle.length - 1; i > -1; i--) {
        this.texta.elemnum.splice(this.texta.poscurseur, 0, acolle[i])
      }
      this.texta.poscurseurIn = false
      this.texta.poscurseurInRac = false
      this.majaffiche('')
    } else {
      this.texta.elemnum.splice(this.texta.poscurseur, 0, { cont: [], racine: true })
      this.texta.poscurseurIn = false
      this.texta.poscurseurInRac = true
      this.texta.poscurseur2 = 0
      this.texta.poscurseurup = true
      this.majaffiche('')
    }
  }

  majaffiche (elem) {
    this.historique.push('majaffiche', elem)

    if (this.disabled) return
    for (let i = this.texta.elemnum.length - 1; i > -1; i--) {
      if (this.texta.elemnum[i] === null) {
        notify(Error('null dans elemnum zsm3'), { historique: this.historique })
        this.texta.elemnum.splice(i, 1)
      }
    }
    let klm
    if (elem === '/') {
      this.gerediv()
      return
    }
    if (elem === 'ù') {
      this.gereracine()
      return
    }
    if (elem !== '') {
      this.bon = undefined
      j3pStyle(this.conteneur, { color: '' })
    }
    if (elem !== '') {
      if (this.texta.poscurseurIn) {
        if (this.texta.poscurseurup) {
          if (this.texta.elemnum[this.texta.poscurseur][0].length > this.limite) {
            const eLemCoNt = this.textaCont
            // on le passe sur fond rouge
            eLemCoNt.style.backgroundColor = '#ff0000'
            // et on le remettra en blanc dans 100ms
            setTimeout(() => { eLemCoNt.style.backgroundColor = '#ffffff' }, 100)
            return
          }
          // if (this.texta.poscurseur2 < 0) this.texta.poscurseur2 = 0
          // if (this.texta.poscurseur2 > this.texta.elemnum[this.texta.poscurseur][0].length) this.texta.poscurseur = this.texta.elemnum[this.texta.poscurseur][0].length
          this.texta.elemnum[this.texta.poscurseur][0].splice(this.texta.poscurseur2, 0, elem)
          this.texta.poscurseur2++
        } else {
          if (this.texta.elemnum[this.texta.poscurseur][1].length > this.limite) {
            const eLemCoNt = this.textaCont
            // on le passe sur fond rouge
            eLemCoNt.style.backgroundColor = '#ff0000'
            // et on le remettra en blanc dans 100ms
            setTimeout(() => { eLemCoNt.style.backgroundColor = '#ffffff' }, 100)
            return
          }
          // if (this.texta.poscurseur2 < 0) this.texta.poscurseur2 = 0
          // if (this.texta.poscurseur2 > this.texta.elemnum[this.texta.poscurseur][1].length) this.texta.poscurseur = this.texta.elemnum[this.texta.poscurseur][1].length
          this.texta.elemnum[this.texta.poscurseur][1].splice(this.texta.poscurseur2, 0, elem)
          this.texta.poscurseur2++
        }
      } else if (this.texta.poscurseurInRac) {
        if ((this.bloqueracine.includes(elem)) || (this.texta.elemnum[this.texta.poscurseur].cont.length > this.limite)) {
          const eLemCoNt = this.textaCont
          // on le passe sur fond rouge
          eLemCoNt.style.backgroundColor = '#ff0000'
          // et on le remettra en blanc dans 100ms
          setTimeout(() => { eLemCoNt.style.backgroundColor = '#ffffff' }, 100)
          return
        }
        // if (this.texta.poscurseur2 < 0) this.texta.poscurseur2 = 0
        // if (this.texta.poscurseur2 > this.texta.elemnum[this.texta.poscurseur].cont.length) this.texta.poscurseur = this.texta.elemnum[this.texta.poscurseur].cont.length
        this.texta.elemnum[this.texta.poscurseur].cont.splice(this.texta.poscurseur2, 0, elem)
        this.texta.poscurseur2++
      } else {
        if (this.texta.elemnum.length > this.limite) {
          const eLemCoNt = this.textaCont
          // on le passe sur fond rouge
          eLemCoNt.style.backgroundColor = '#ff0000'
          // et on le remettra en blanc dans 100ms
          setTimeout(() => { eLemCoNt.style.backgroundColor = '#ffffff' }, 100)
          return
        }
        // if (this.texta.poscurseur < 0) this.texta.poscurseur = 0
        // if (this.texta.poscurseur > this.texta.elemnum.length) this.texta.poscurseur = this.texta.elemnum
        this.texta.elemnum.splice(this.texta.poscurseur, 0, elem)
        this.texta.poscurseur++
      }
    }
    /// verif 2 chiffres cote a cote

    this.majAfficheHelper2()
    if (this.sansBord) this.textaCont.style.border = '0px solid black'
    if (this.petiteFont) this.textaCont.style.fontSize = '16px'
    let bufel, elti, eltCi
    for (const [i, elem] of this.texta.elemnum.entries()) {
      if (elem !== undefined) {
        if (Array.isArray(elem)) {
          const ttabDiv = addTable(this.unTAbc[0][2 * i + 1], { nbLignes: 3, nbColonnes: 1, className: 'zoneS3' })
          const ttabDivc = getCells(ttabDiv)
          const ttabR = addTable(ttabDivc[0][0], { nbLignes: 1, nbColonnes: elem[0].length * 2 + 1, className: 'zoneS3' })
          const ttabRc = getCells(ttabR)
          const ttabR2 = addTable(ttabDivc[2][0], {
            nbLignes: 1,
            nbColonnes: elem[1].length * 2 + 1,
            className: 'zoneS3'
          })
          const ttabRc2 = getCells(ttabR2)
          this.tabRac[i] = { num: ttabRc[0], den: ttabRc2[0] }
          ttabDivc[1][0].classList.add('height1Black')
          for (klm = 0; klm < elem[0].length; klm++) {
            elti = ttabRc[0][2 * klm]
            eltCi = ttabRc[0][2 * klm + 1]
            if (elem[0][klm] === ' ') {
              eltCi.innerHTML = '&nbsp;'
            } else {
              j3pAffiche(eltCi, null, '$' + elem[0][klm] + '$')
            }
            eltCi.num = i
            eltCi.num3 = klm
            eltCi.tab = true
            eltCi.tabnum = true
            eltCi.num2 = 0
            elti.num = i
            elti.num2 = 0
            elti.num3 = klm
            elti.tab = true
            elti.tabnum = true
            elti.tabIndex = 0
            eltCi.addEventListener('click', this._clickcListener, false)
            elti.addEventListener('focus', this._metCurseurListener, false)
            elti.addEventListener('keydown', this._clavierListener, false)
            // @todo expliquer pourquoi il faut ajouter un listener qui supprime la propagation de l’événement pour keypress et keyup
            elti.addEventListener('keypress', this._vireListener, false)
            elti.addEventListener('keyup', this._vireListener, false)
            eltCi.classList.add('noMarginPadding')
          }
          elti = ttabRc[0][2 * klm]
          elti.num = i
          elti.num2 = 0
          if (klm === 0) {
            elti.innerHTML = '&nbsp;&nbsp;'
            elti.style.backgroundColor = '#aaaaaa'
            elti.tab = true
            elti.tabnum = true
            elti.num3 = 0
            elti.addEventListener('click', this._clickcListener, false)
          }
          elti.tabIndex = 0
          elti.addEventListener('focus', this._metCurseurListener, false)
          elti.addEventListener('keydown', this._clavierListener, false)
          // @todo expliquer pourquoi il faut ajouter un listener qui supprime la propagation de l’événement pour keypress et keyup
          // suis pas sur, mais sinon ca equivaut a une touche clavier sur la page
          // si c’est backspace, ca recharge la page, c’est pas rigolo
          elti.addEventListener('keypress', this._vireListener, false)
          elti.addEventListener('keyup', this._vireListener, false)
          elti.classList.add('noMarginPadding')
          for (klm = 0; klm < elem[1].length; klm++) {
            elti = ttabRc2[0][2 * klm]
            eltCi = ttabRc2[0][2 * klm + 1]
            if (elem[1][klm] === ' ') {
              eltCi.innerHTML = '&nbsp;'
            } else {
              j3pAffiche(eltCi, null, '$' + elem[1][klm] + '$')
            }
            elti.tabIndex = 0
            eltCi.num = i
            eltCi.num3 = klm
            eltCi.tab = true
            eltCi.tabnum = false
            eltCi.num2 = 0
            elti.num = i
            elti.num2 = 0
            eltCi.addEventListener('click', this._clickcListener, false)
            elti.addEventListener('focus', this._metCurseurListener, false)
            elti.addEventListener('keydown', this._clavierListener, false)
            // @todo expliquer pourquoi il faut ajouter un listener qui supprime la propagation de l’événement pour keypress et keyup
            elti.addEventListener('keypress', this._vireListener, false)
            elti.addEventListener('keyup', this._vireListener, false)
            eltCi.classList.add('noMarginPadding')
          }
          elti = ttabRc2[0][2 * klm]
          elti.tabIndex = 0
          if (klm === 0) {
            elti.innerHTML = '&nbsp;&nbsp;'
            elti.style.backgroundColor = '#aaaaaa'
            elti.tab = true
            elti.tabnum = false
            elti.num3 = 0
            elti.addEventListener('click', this._clickcListener, false)
          }
          elti.num = i
          elti.num2 = 0
          elti.addEventListener('focus', this._metCurseurListener, false)
          elti.addEventListener('keydown', this._clavierListener, false)
          // @todo expliquer pourquoi il faut ajouter un listener qui supprime la propagation de l’événement pour keypress et keyup
          elti.addEventListener('keypress', this._vireListener, false)
          elti.addEventListener('keyup', this._vireListener, false)
          elti.classList.add('noMarginPadding')

          elti = this.unTAbc[0][2 * i]
          elti.tabIndex = 0
          elti.addEventListener('focus', this._metCurseurListener, false)
          elti.addEventListener('keydown', this._clavierListener, false)
          elti.addEventListener('keypress', this._vireListener, false)
          elti.addEventListener('keyup', this._vireListener, false)
          // elti.classList.add('noMarginPadding')
        } else if (elem.racine === true) {
          const ttabR = addTable(this.unTAbc[0][2 * i + 1], {
            nbLignes: 1,
            nbColonnes: elem.cont.length * 2 + 2,
            className: 'zoneS3'
          })
          const ttabRc = getCells(ttabR)
          this.tabRac[i] = ttabRc[0]
          ttabRc[0][0].classList.add('zsmRacine')
          ttabRc[0][0].innerHTML = '&nbsp;'
          for (klm = 0; klm < elem.cont.length; klm++) {
            elti = ttabRc[0][2 * klm + 1]
            eltCi = ttabRc[0][2 * klm + 2]
            if (elem.cont[klm] === ' ') {
              eltCi.innerHTML = '&nbsp;'
            } else {
              j3pAffiche(eltCi, null, '$' + elem.cont[klm] + '$')
            }
            eltCi.num = i
            eltCi.num3 = klm
            eltCi.rac = true
            eltCi.tabnum = true
            eltCi.num2 = 0
            elti.num = i
            elti.num2 = 0
            elti.num3 = klm
            elti.rac = true
            elti.tabnum = true
            elti.tabIndex = 0
            j3pStyle(elti, { fontSize: '100%' })
            j3pStyle(eltCi, { fontSize: '100%' })
            // abracedabra
            eltCi.addEventListener('click', this._clickcListener, false)
            elti.addEventListener('focus', this._metCurseurListener, false)
            elti.addEventListener('keydown', this._clavierListener, false)
            // @todo expliquer pourquoi il faut ajouter un listener qui supprime la propagation de l’événement pour keypress et keyup
            elti.addEventListener('keypress', this._vireListener, false)
            elti.addEventListener('keyup', this._vireListener, false)
            eltCi.classList.add('noMarginPadding')
            eltCi.classList.add('borderTop1')
            elti.classList.add('borderTop1')
          }
          elti = ttabRc[0][2 * klm + 1]
          elti.tabIndex = 0
          elti.num = i
          elti.num2 = 0
          if (klm === 0) {
            elti.innerHTML = '&nbsp;&nbsp;'
            elti.style.backgroundColor = '#aaaaaa'
          }
          elti.addEventListener('focus', this._metCurseurListener, false)
          elti.addEventListener('keydown', this._clavierListener, false)
          elti.addEventListener('keypress', this._vireListener, false)
          elti.addEventListener('keyup', this._vireListener, false)
          elti.classList.add('noMarginPadding')
          elti.classList.add('borderTop1')

          elti = this.unTAbc[0][2 * i]
          elti.tabIndex = 0
          elti.addEventListener('focus', this._metCurseurListener, false)
          elti.addEventListener('keydown', this._clavierListener, false)
          elti.addEventListener('keypress', this._vireListener, false)
          elti.addEventListener('keyup', this._vireListener, false)
        } else {
          bufel = elem
          elti = this.unTAbc[0][2 * i]
          eltCi = this.unTAbc[0][2 * i + 1]
          if (bufel.includes('widehat')) {
            j3pStyle(eltCi, { fontSize: '85%' })
            eltCi.vAlign = 'top'
          }
          if (bufel === ' ') {
            eltCi.innerHTML = '&nbsp;'
          } else {
            j3pAffiche(eltCi, null, '$' + elem + '$')
          }
          eltCi.num = i
          eltCi.num2 = 0
          elti.num = i
          elti.num2 = 0
          elti.tabIndex = 0
          eltCi.addEventListener('click', this._clickcListener, false)
          elti.addEventListener('focus', this._metCurseurListener, false)
          elti.addEventListener('keydown', this._clavierListener, false)
          // @todo expliquer pourquoi il faut ajouter un listener qui supprime la propagation de l’événement pour keypress et keyup
          elti.addEventListener('keypress', this._vireListener, false)
          elti.addEventListener('keyup', this._vireListener, false)
          // eltCi.classList.add('noMarginPadding')
        }
      }
    }
    // en fait faut faire une fois de plus pour la dernièrer zone de saisie (tout à droite)
    // exactement la mm boucle que au dessus je la met à la fin
    elti = this.unTAbc[0][this.unTAbc[0].length - 1]
    elti.tabIndex = 0
    elti.addEventListener('focus', this._metCurseurListener, false)
    elti.addEventListener('keydown', this._clavierListener, false)
    elti.addEventListener('keypress', this._vireListener, false)
    elti.addEventListener('keyup', this._vireListener, false)
    elti.classList.add('noMarginPadding')
    if (this.texta.elemnum.length === 0) {
      this.unTAbc[0][0].innerHTML = '&nbsp;&nbsp;'
    }

    this.textaIm.addEventListener('mousedown', this._placeListener, false)
    this.textaIm.style.cursor = 'pointer'

    this.textaTab.style.width = (Math.min(this.textaCont.offsetWidth, 10) + this.textaIm.offsetWidth) + 'px'

    this.textaCont.classList.add('zsmMqFocused')
    this.textaIm.classList.add('zsmMq')

    this.majAfficheHelper()

    if (!this.isblur) {
      if (this.texta.poscurseurIn) {
        let tt
        if (!this.texta.poscurseurup) {
          tt = this.tabRac[this.texta.poscurseur].den
        } else {
          tt = this.tabRac[this.texta.poscurseur].num
        }
        tt[Math.min(this.texta.poscurseur2 * 2, tt.length - 1)].focus()
      } else if (this.texta.poscurseurInRac) {
        this.tabRac[this.texta.poscurseur][this.texta.poscurseur2 * 2 + 1].focus()
      } else {
        this.unTAbc[0][Math.min(this.texta.poscurseur * 2, this.unTAbc[0].length - 1)].focus()
      }
    }
    if (this.bon === false) this.corrige(false)
    if (!this.blok && typeof this.onchange === 'function') this.onchange()
  } // majaffiche

  metcurseur (ki) {
    this.historique.push('metcurseur', ki)

    ki.currentTarget.classList.add('zsmMqFocusedCursor')
  }

  rep () {
    this.historique.push('rep')

    const ret = []
    let encours = false
    let buf = ''
    for (const elem of this.texta.elemnum) {
      if (elem === ' ') {
        if (encours) {
          ret.push(buf)
        }
        buf = ''
        encours = false
      } else if ((elem === '+') || (elem === '-') || (elem === '×')) {
        if (encours) {
          ret.push(buf)
        }
        buf = ''
        ret.push(elem)
        encours = false
      } else if (Array.isArray(elem)) {
        encours = true
        buf += 'ù'
        for (let j = 0; j < elem[0].length; j++) {
          buf += elem[0][j]
        }
        buf += '#'
        for (let j = 0; j < elem[1].length; j++) {
          buf += elem[1][j]
        }
        buf += '@'
      } else {
        encours = true
        buf += elem
      }
    }
    if (buf !== '') {
      ret.push(buf)
    }
    return ret
  }

  reponse () {
    this.historique.push('reponse')

    let rep = ''
    for (const elem of this.texta.elemnum) {
      if (elem === '{}^2') {
        rep += '^{2}'
      } else if (elem === '{}^3') {
        rep += '^{3}'
      } else if (Array.isArray(elem)) {
        rep += '\\frac{'
        for (let j = 0; j < elem[0].length; j++) {
          rep += elem[0][j]
        }
        rep += '}{'
        for (let j = 0; j < elem[1].length; j++) {
          rep += elem[1][j]
        }
        rep += '}'
      } else if (elem?.racine === true) {
        rep += '\\racine{'
        for (let j = 0; j < elem.cont.length; j++) {
          rep += elem.cont[j]
        }
        rep += '}'
      } else {
        rep += elem
      }
    }

    return rep
  }

  vire (event) {
    this.historique.push('vire', event)

    event.preventDefault()
    event.stopPropagation()
  }
}

export default ZoneStyleMathquill3