legacy/core/functionsJqDialog.js

import $ from 'jquery'
import { j3pAddElt, j3pAjouteBouton, j3pC, j3pElement } from 'src/legacy/core/functions'

/**
 * Regroupe les fonctions qui gère les boîtes de dialogue jQuery
 * @module legacy/core/functions.jqdialog
 */

function getJqFenetre (name) {
  const $elt = $(`div[name="${name}"]`)
  if ($elt && typeof $elt.dialog === 'function') return $elt
  if ($elt) console.error(Error(`On a trouvé un div avec name=${name} mais ce n’est pas une boite de dialogue jQuery`))
  else console.error(Error('Pas de boîte de dialogue ' + name))
}

/**
 * Affiche ou masque (suivant l’état courant) les fenêtres dont les noms sont passés en argument
 * @param {...string} names un ou des noms de fenêtre
 */
export function j3pToggleFenetres (...names) {
  for (const name of names) {
    const $elt = getJqFenetre(name)
    if ($elt) {
      if ($elt.dialog('isOpen')) {
        $elt.dialog('close')
      } else {
        $elt.dialog('open')
      }
    }
  }
}

/**
 * Ferme le dialog jQuery name
 * @param {string} name
 */
export function j3pMasqueFenetre (name) {
  const $elt = getJqFenetre(name)
  if (!$elt) return
  if ($elt.dialog('isOpen')) $elt.dialog('close')
}

/**
 * Détruit les fenêtres dont les noms sont passés en argument
 * @param {...string} names un ou des noms de fenêtre
 */
export function j3pDetruitFenetres (...names) {
  for (const name of names) {
    getJqFenetre(name)?.dialog('destroy')
    // faut aussi virer le div parent
    const div = document.querySelector(`.fenetre[name="${name}"]`)
    if (div) div.parentNode.removeChild(div)
  }
}

/**
 * Détruit toutes les fenêtres créées par j3pCreeFenetres
 */
export function j3pDetruitToutesLesFenetres () {
  const dialog = j3pElement('dialog', null)
  if (dialog) $(dialog).dialog('destroy')
  for (const fenetre of document.querySelectorAll('.fenetre')) {
    $(fenetre).dialog('destroy')
    fenetre.parentNode.removeChild(fenetre)
  }
}

/**
 * Crée les boutons
 * @param {HTMLElement|string} conteneur
 * @param opts
 */
export function j3pCreeBoutonsFenetre (conteneur, opts) {
  let top = 10
  for (const opt of opts) {
    const [nom, label] = opt
    j3pCreeBoutonFenetre(nom, conteneur, { top, left: 20 }, label)
    top += 50
  }
}

/**
 * Ajoute un bouton pour afficher / masquer le dialog nom
 * @param {string} nom
 * @param {HTMLElement|string} conteneur
 * @param {{top: number, left: number}} [position]
 * @param label
 * @returns {HTMLElement} l’input ou le bouton
 */
export function j3pCreeBoutonFenetre (nom, conteneur, position, label) {
  if (typeof position === 'string') {
    label = position
    position = null
  }
  const props = {}
  if (position?.top) {
    props.style = {
      position: 'absolute',
      top: position.top,
      left: position.left
    }
  } else {
    props.style = {
      paddingTop: '5px'
    }
  }
  const div = j3pAddElt(conteneur, 'div', '', props)
  return j3pAjouteBouton(div, j3pToggleFenetres.bind(null, nom), { id: 'BTN_fenetre' + nom, className: 'MepBoutonsFenetre', value: label })
}

/**
 * Crée les popup jQueryUi dialog d’après parcours.fenetresjq (ajoute toujours un dialog "Bilan")
 * Attention, top et left ne sont pris en compte que pour la première fenêtre de la liste (pourquoi ? mystère…)
 * @param {Parcours} parcours
 */
export function j3pCreeFenetres (parcours) {
  // https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/some
  const fenetreExiste = (name) => fenetresDatas.some(arg => arg.name === name)

  // des objets { name, title, left, top, … } servant à définir la boite de dialogue jQuery
  const fenetresDatas = parcours.fenetresjq

  j3pDetruitToutesLesFenetres()

  if (!fenetreExiste('Bilan')) {
    fenetresDatas.push({
      name: 'Bilan',
      title: 'Bilan',
      width: 400,
      left: 700,
      top: 150,
      id: 'fenetreBilan'
    })
  }

  fenetresDatas.forEach((fenetre, k) => {
    const { id, name, title, height = 'auto', width = 'auto', left, right, top, bottom, noClose = false, calcOpts = {} } = fenetre

    // on ajoute le div dans body (l’appel de .dialog() le remettra dans un autre div créé par jQueryUi)
    const divDialog = j3pAddElt(document.body, 'div', '', {
      id: 'dialog' + name,
      name,
      className: 'fenetre',
      title
    })
    if (id) {
      // on ajoute un autre div avec cet id dedans
      j3pAddElt(divDialog, 'div', '', { id })
    }

    // on crée la boite de dialogue, datas de base
    const dialogOptions = {
      width,
      maxHeight: 500,
      autoOpen: false,
      resizable: false,
    }
    const isCalc = name === 'Calculatrice'

    // puis les cas particuliers
    if (k === 0 && !isCalc) {
      // positionne la 1re fenêtre déclarée si c'est pas une calculatrice
      // ce code sert à redéfinir la position du dialog lorsqu’il s’ouvre
      // (pourquoi tout ça ???)
      const { x, y } = j3pC()
      const cssOpts = {
        'min-width': '280px'
      }
      // on regarde en fonction de ce que l’on nous passe
      if (bottom != null) cssOpts.bottom = bottom + y
      else cssOpts.top = (top ?? 30) + y
      if (right != null) cssOpts.right = right
      else cssOpts.left = (left ?? 30) + x
      dialogOptions.open = function () {
        $(this).parent().css(cssOpts)
      }
    }

    if (name === 'Bilan') {
      dialogOptions.title = 'BILAN'
      dialogOptions.beforeClose = function () {
        parcours.debutdelasection = true
        parcours.sectionCourante()
      }
    } else if (name === 'Boutons') {
      dialogOptions.height = (fenetresDatas.length) * 50 + 10
    } else if (isCalc) {
      // on veut toujours caler la calculatrice en haut à droite
      // cf https://api.jqueryui.com/dialog/
      // top & left & co sont ignorés, faut utiliser position
      // Cf https://api.jqueryui.com/position/
      dialogOptions.position = {
        my: 'right top',
        // le xx est ignoré dans right+xx, pourquoi ? pas grave c’est collé à droite
        at: 'right top+200', // on décale sous le score, un peu plus loin, car le bouton calculatrice est souvent là
        of: '#Mepact'
      }
    } else if (height) {
      dialogOptions.height = height
    } else {
      dialogOptions.minHeight = 100
    }
    if (noClose) {
      // cf cf https://api.jqueryui.com/dialog/
      dialogOptions.dialogClass = 'no-close'
    }

    // on peut créer les boîtes
    const boite = $(divDialog).dialog(dialogOptions)

    if (isCalc) {
      // on met une calculatrice dedans
      const ct = boite[0]
      import('src/lib/outils/calculatrice/Calculatrice')
        .then(({ default: Calculatrice }) => {
          calcOpts.theme = 'noBorder'
          Calculatrice.create(ct, calcOpts)
        })
        .catch((error) => console.error(error))
      try {
        ct.parentElement.style.padding = '0'
      } catch (error) {
        console.error(error)
      }
    }
  }) // forEach fenetresDatas
} // j3pCreeFenetres