import { j3pAddContent, j3pAddElt, j3pDetruit, j3pDiv, j3pElement, j3pGetNewId, j3pSpan, j3pStyle } from 'src/legacy/core/functions'
import { j3pCreeSVG } from 'src/legacy/core/functionsSvg'
import ecouteImg from 'src/legacy/sections/college/etikMake/ecoute.png'
import { addDefaultTable } from 'src/legacy/themes/table'
import { getJ3pConteneur } from 'src/lib/core/domHelpers'
import { j3pAffiche } from 'src/lib/mathquill/functions'
import BulleAide from 'src/legacy/outils/bulleAide/BulleAide'
import './etiquette.css'
/**
* À décrire
* @param {string} iddivconteneur
* @param {string} manouvellediv
* @param {string[]} montab
* @param {Object} parametres
* @param {boolean[]} parametres.mathquill à décrire
* @param {function} [parametres.afaire] à décrire
* @param {number} [parametres.width=0] à décrire
* @param {boolean} [parametres.centre] à décrire
* @param {boolean} [parametres.cacheAide] à décrire
* @param {boolean} [parametres.reutilisable] à décrire
* @param {string} [parametres.dispo=carre] à décrire (doit valoir fixe|lignes|colonnes|carre)
* @param {number} [parametres.colonne] à décrire
* @param {number} [parametres.ligne] à décrire
* @param {string} [parametres.couleur=#C0C0C0] à décrire
* @param {number} [parametres.limite=15] à décrire
* @param {objet} [parametres.mtgAppLecteur] mtgAppLEcteur ( si yen a besoin )
* @param {objet} [parametres.mtgAppLecteur] codePlace ( Si y’a besoin de distinguer les places entre elles )
* @constructor
*/
function Etiquettes (iddivconteneur, manouvellediv, montab, parametres) {
this.cooplace = []
this.montab = montab
this.ongoingTouches = []
this.disabled = false
this.direct = parametres.direct
/// si on veut déclencher une fonction sur un changement
// mettre etiq pour recuperer le num de l’étiquette
// contenu pour recupere le contenu
// place pour recup le num de la place
if (parametres.afaire === undefined) {
this.afaire = function () {}
} else {
if (typeof parametres.afaire !== 'function') throw Error('afaire doit être une fonction')
this.afaire = parametres.afaire
}
this.mtgAppLecteur = parametres.mtgAppLecteur ?? undefined
this.codePlace = parametres.codePlace ?? undefined
if (typeof parametres.width === 'number') {
this.tailledonnee = parametres.width
} else {
this.tailledonnee = 0
}
// pour des trucs centré
const uncentre = parametres.centre
// FIXME un booléen devrait pas admettre plusieurs valeurs…
this.centre = ((uncentre === true) || (uncentre === 'true') || (uncentre === 'oui'))
// pour des etiquettes a usage unique
// @todo mettre le meme nom pour le paramètre et la propriété de l’objet (choisir entre reutilisable et unique)
const unique = parametres.reutilisable
// FIXME un booléen devrait pas admettre plusieurs valeurs…
this.unique = ((unique === false) || (unique === 'false') || (unique === 'non'))
/// dispo des etiquettes
const dispo = parametres.dispo
const nbcol = parametres.colonne
const nbligne = parametres.ligne
let ya = false
if (Number.isInteger(nbcol)) {
this.col = nbcol
ya = true
} else { this.col = 0 }
if (Number.isInteger(nbligne)) {
this.lig = nbligne
ya = true
} else {
this.lig = 0
}
// @todo réduire le nb de cas folkloriques ;-), à faire au moment de l’affectation avec par ex
// this.dispo = ['fixe', 'lignes', 'colonnes', 'carre'].includes(parametres.dispo) ? parametres.dispo : 'carre'
if ((dispo === 'Fixe') || (dispo === 'Fixé') || (dispo === 'fixe') || (dispo === 'fixé')) { if (ya) { this.dispo = 'fixe' } }
if ((dispo === 'ligne') || (dispo === 'lignes') || (dispo === 'line') || (dispo === 'lines')) { this.dispo = 'lignes' }
if ((dispo === 'colonnes') || (dispo === 'colonne') || (dispo === 'row') || (dispo === 'rows')) { this.dispo = 'colonnes' }
if ((this.dispo !== 'lignes') && (this.dispo !== 'colonnes') && (this.dispo !== 'fixe')) { this.dispo = 'carre' }
this.couleur = parametres.couleur || '#C0C0C0'
this.limite = parametres.limite || 15
/// /fin des parametres
this.iddivconteneur = iddivconteneur
if (typeof iddivconteneur === 'string') this.iddivconteneur = j3pElement(iddivconteneur)
try {
this.parent = getJ3pConteneur(this.iddivconteneur)
} catch (e) {
this.parent = document.body
}
try {
this.mepact = getJ3pConteneur(this.parent)
} catch (e) {
this.mepact = document.body
}
if (!this.parent) {
this.parent = document.body
} else if (this.parent.URL) this.parent = document.body
if (!this.mepact) {
this.mepact = document.body
} else if (this.mepact.URL) this.mepact = document.body
const yui = addDefaultTable(iddivconteneur, 1, 3)
yui[0][0].style.padding = '0px'
yui[0][1].style.padding = '0px'
yui[0][1].style.width = '5px'
yui[0][2].style.padding = '0px'
this.spanContenant = yui[0][0]
if (!parametres.cacheAide) this.llaide = new BulleAide(yui[0][2], '1.Clique pour attraper. <br> 2.Clique pour déposer.', {})
this.spanContenant.classList.add('zonelistetexte')
this.spantexte = j3pSpan(this.spanContenant, {
className: 'zonelistetexte'
})
this.nb = this.montab.length
switch (this.dispo) {
case 'lignes' :
this.ligne = 1
this.colonne = this.nb
break
case 'colonnes' :
this.ligne = this.nb
this.colonne = 1
break
case 'carre' :
this.ligne = Math.floor(Math.sqrt(this.nb))
this.colonne = Math.ceil(this.nb / this.ligne)
break
case 'fixe' :
if (this.col !== 0) {
this.colonne = this.col
this.ligne = Math.ceil(this.nb / this.col)
} else {
this.ligne = this.lig
this.colonne = Math.ceil(this.nb / this.lig)
}
}
// crea tab des bases etiquettes
this.whEtkl = []
this.tabEtikDou = addDefaultTable(this.spantexte, this.ligne, this.colonne * 2)
for (let i = 0; i < this.tabEtikDou.length; i++) {
for (let j = 0; j < this.tabEtikDou[i].length - 1; j += 2) {
this.tabEtikDou[i][j + 1].style.width = '10px'
}
}
this.listdivchoix = -1
this.etiqok = []
this.divARet = []
for (let i = 0; i < montab.length; i++) {
const io = Math.ceil((i + 1) / this.colonne) - 1
const j = ((i + 1) - 1) % (this.colonne)
let buf = this.montab[i]
if (Array.isArray(buf)) {
// en fait ca peut etre un tableau de tableau si y’a des accords a prévoir (s au pluriel)
buf = buf[0]
}
for (let mm = 0; mm < this.montab.length; mm++) {
const div2 = j3pDiv(this.tabEtikDou[io][j * 2])
div2.setAttribute('class', 'etiquetteCache')
let buf2 = this.montab[mm]
if (Array.isArray(buf2)) {
// en fait ca peut etre un tableau de tableau si y’a des accords a prévoir (s au pluriel)
buf2 = buf2[0]
}
if (typeof buf2 === 'string') {
j3pAffiche(div2, null, buf2)
} else {
const el = buf2
switch (el.type) {
case undefined:
case 'mathgraph': {
const ui = addDefaultTable(div2, 1, 1)[0][0]
const newId = j3pGetNewId('mtgetih')
const svg = j3pCreeSVG(ui, { id: newId, width: 37 + el.content.width * 340, height: 54 + el.content.height * 253 })
this.mtgAppLecteur.addDoc(newId, el.content.txtFigure, true)
svg.style.position = 'relative'
}
break
case 'image': {
const limm = j3pAddElt(div2, 'img', '', { src: el.content.txtFigure, width: el.content.width, height: el.content.height })
limm.style.width = el.content.width + 'px'
limm.style.height = el.content.height + 'px'
limm.style.marginTop = '2px'
limm.style.marginBottom = '2px'
}
break
case 'son': {
const ui2 = addDefaultTable(div2, 1, 1)[0][0]
const limm = j3pAddElt(ui2, 'img', '', { src: ecouteImg, width: '20px', height: '20px' })
limm.style.width = '20px'
limm.style.height = '20px'
j3pAddContent(ui2, 'n° ' + mm)
}
}
}
}
const div = j3pDiv(this.tabEtikDou[io][j * 2])
const divSon = j3pDiv(this.tabEtikDou[io][j * 2 + 1])
this.whEtkl[i] = this.tabEtikDou[io][j * 2]
div.setAttribute('class', 'etiquette2')
this.etiqok[i] = true
if (typeof buf === 'string') {
const hjkl = j3pAffiche(div, null, buf)
for (let uu = 0; uu < hjkl.mqList.length; uu++) {
if (hjkl.mqList[uu] !== null) hjkl.mqList[uu].style.cursor = 'pointer'
}
}
div.style.background = this.couleur
div.addEventListener('click', (event) => this.create(i, event), false)
this.divARet.push({ princ: div, divSon })
}
this.place2Listener = this.place2.bind(this)
this.mepact.addEventListener('mousemove', this.place2Listener, false)
} // Etiquettes
Etiquettes.prototype.rac = function rac () {
j3pDetruit(this.listdivchoix)
const uni = this.listdivchoix.num
this.listdivchoix = -1
for (let i = 0; i < this.cooplace.length; i++) {
if (this.cooplace[i][2].etiq === -1) {
this.cooplace[i][2].contenu = this.montab[uni]
this.cooplace[i][2].etiq = uni
this.cooplace[i][2].ecris()
if (this.unique) {
this.whEtkl[uni].style.visibility = 'hidden'
this.etiqok[uni] = false
}
return
}
}
if (this.unique) {
this.whEtkl[uni].style.visibility = undefined
this.etiqok[uni] = true
}
}
Etiquettes.prototype.create = function create (indexEtiquette, event) {
if (this.disabled) return
this.verifCoPla()
if (!this.etiqok[indexEtiquette]) return
let buf = this.montab[indexEtiquette]
if (Array.isArray(buf)) { buf = buf[0] }
this.listdivchoix = j3pDiv(this.mepact)
this.listdivchoix.num = indexEtiquette
for (let mm = 0; mm < this.montab.length; mm++) {
const div2 = j3pDiv(this.listdivchoix)
div2.setAttribute('class', 'etiquetteCache')
div2.style.fontSize = '20px'
let buf2 = this.montab[mm]
if (Array.isArray(buf2)) {
// en fait ca peut etre un tableau de tableau si y’a des accords a prévoir (s au pluriel)
buf2 = buf2[0]
}
if (typeof buf2 === 'string') {
j3pAffiche(div2, null, buf2)
} else {
const el = buf2
switch (el.type) {
case undefined:
case 'mathgraph': {
const ui = addDefaultTable(div2, 1, 1)[0][0]
const newId = j3pGetNewId('mtgetih')
const svg = j3pCreeSVG(ui, { id: newId, width: 37 + el.content.width * 340, height: 54 + el.content.height * 253 })
this.mtgAppLecteur.addDoc(newId, el.content.txtFigure, true)
svg.style.position = 'relative'
}
break
case 'image': {
const limm = j3pAddElt(div2, 'img', '', { src: el.content.txtFigure, width: el.content.width, height: el.content.height })
limm.style.width = el.content.width + 'px'
limm.style.height = el.content.height + 'px'
limm.style.marginTop = '2px'
limm.style.marginBottom = '2px'
}
break
case 'son': {
const ui2 = addDefaultTable(div2, 1, 1)[0][0]
const limm = j3pAddElt(ui2, 'img', '', { src: ecouteImg, width: '20px', height: '20px' })
limm.style.width = '20px'
limm.style.height = '20px'
j3pAddContent(ui2, 'n° ' + mm)
}
}
}
}
this.listdivchoix.setAttribute('class', 'etiquette3')
this.listdivchoix.style.fontSize = '20px'
this.listdivchoix.style.fontFamily = 'Roboto, "Noto Emoji", sans-serif'
this.listdivchoix.style.background = this.couleur
if (typeof buf === 'string') {
const hjkl = j3pAffiche(this.listdivchoix, null, buf)
for (let uu = 0; uu < hjkl.mqList.length; uu++) {
if (hjkl.mqList[uu] !== null) hjkl.mqList[uu].style.cursor = 'pointer'
}
} else {
const el = buf
switch (el.type) {
case undefined:
case 'mathgraph': {
const ui = addDefaultTable(this.listdivchoix, 1, 1)[0][0]
const newId = j3pGetNewId('mtgetih')
j3pCreeSVG(ui, { id: newId, width: 37 + el.content.width * 340, height: 54 + el.content.height * 253 })
this.mtgAppLecteur.addDoc(newId, el.content.txtFigure, true)
this.mtgAppLecteur.calculate(newId)
this.mtgAppLecteur.display(newId)
}
break
case 'image': {
const limm = j3pAddElt(this.listdivchoix, 'img', '', { src: el.content.txtFigure, width: el.content.width, height: el.content.height })
limm.style.width = el.content.width + 'px'
limm.style.height = el.content.height + 'px'
limm.style.marginTop = '2px'
limm.style.marginBottom = '2px'
}
break
case 'son': {
const ui2 = addDefaultTable(this.listdivchoix, 1, 1)[0][0]
const limm = j3pAddElt(ui2, 'img', '', { src: ecouteImg, width: '20px', height: '20px' })
limm.style.width = '20px'
limm.style.height = '20px'
j3pAddContent(ui2, 'n° ' + indexEtiquette)
}
}
}
this.listdivchoix.bloque = false
const { left, top } = this.mepact.getBoundingClientRect()
this.listdivchoix.style.left = (event.clientX - left - this.listdivchoix.offsetWidth / 2) + 'px'
this.listdivchoix.style.top = (event.clientY - top - this.listdivchoix.offsetHeight / 2) + 'px'
this.listdivchoix.addEventListener('click', (event) => this.place(event), false)
this.listdivchoix.addEventListener('touchstart', this._handleStart.bind(this), { capture: false, passive: false })
this.listdivchoix.addEventListener('touchend', this._handleEnd.bind(this), false)
this.listdivchoix.addEventListener('touchcancel', this._handleCancel.bind(this), false)
this.listdivchoix.addEventListener('touchleave', this._handleLeave.bind(this), false)
this.listdivchoix.addEventListener('touchmove', this._handleMove.bind(this), { capture: false, passive: false })
// FIXME mafoncez n’existe pas
if (this.unique) {
this.whEtkl[indexEtiquette].style.visibility = 'hidden'
this.etiqok[indexEtiquette] = false
}
if (event.ctrlKey || this.direct) { this.rac() }
}
Etiquettes.prototype.place = function place (event) {
if (event.ctrlKey || this.direct) {
this.rac()
return
}
if (this.disabled) { return }
if (this.listdivchoix.bloque) {
if (this.listdivchoix.place.etiq !== -1) {
if (!this.unique) {
try {
this.whEtkl[this.listdivchoix.num].style.visibility = undefined
this.etiqok[this.listdivchoix.num] = true
} catch (e) {
return
}
} else {
try {
this.whEtkl[this.listdivchoix.place.etiq].style.visibility = 'visible'
this.etiqok[this.listdivchoix.place.etiq] = true
} catch (e) {
return
}
}
}
this.listdivchoix.place.contenu = this.montab[this.listdivchoix.num]
this.listdivchoix.place.etiq = this.listdivchoix.num
this.listdivchoix.place.ecris()
if (!this.unique) {
this.whEtkl[this.listdivchoix.num].style.visibility = undefined
this.etiqok[this.listdivchoix.num] = true
}
} else {
if (!this.unique) {
this.whEtkl[this.listdivchoix.num].style.visibility = undefined
this.etiqok[this.listdivchoix.num] = true
} else {
if (!this.whEtkl[this.listdivchoix.num]) {
return
}
this.whEtkl[this.listdivchoix.num].style.visibility = 'visible'
this.etiqok[this.listdivchoix.num] = true
}
}
j3pDetruit(this.listdivchoix)
this.listdivchoix = -1
}
Etiquettes.prototype.place2 = function place2 (event) {
if (this.disabled || (this.listdivchoix === -1)) return
j3pStyle(this.listdivchoix, { zIndex: 700 })
const { left, top } = this.mepact.getBoundingClientRect()
const x = event.clientX - left
const y = event.clientY - top
let bloque = false
const lim = this.limite
let nub
for (let i = 0; i < this.cooplace.length; i++) {
if ((Math.abs(x - this.cooplace[i][0]) < lim) && (Math.abs(y - this.cooplace[i][1]) < lim)) {
bloque = true
nub = i
break
}
}
this.listdivchoix.bloque = bloque
if (bloque) {
this.listdivchoix.place = this.cooplace[nub][2]
this.listdivchoix.style.left = (this.cooplace[nub][0] - this.listdivchoix.offsetWidth / 2) + 'px'
this.listdivchoix.style.top = (this.cooplace[nub][1] - this.listdivchoix.offsetHeight / 2) + 'px'
this.listdivchoix.style.border = '1px solid red'
} else {
this.listdivchoix.style.border = '1px solid black'
this.listdivchoix.style.left = (x - this.listdivchoix.offsetWidth / 2) + 'px'
this.listdivchoix.style.top = (y - this.listdivchoix.offsetHeight / 2) + 'px'
}
}
Etiquettes.prototype.supprimemoi = function supprimemoi (obj) {
for (let i = 0; i < this.cooplace.length; i++) {
if ((this.cooplace[i][2].iddivconteneur === obj.iddivconteneur) && (this.cooplace[i][2].manouvellediv === obj.manouvellediv)) {
this.cooplace.splice(i, 1)
}
}
}
Etiquettes.prototype.envoieCoo = function envoieCoo (x, y, z) {
this.cooplace.push([x, y, z])
}
Etiquettes.prototype.verifCoPla = function verifCoPla () {
const coolplabuf = this.cooplace
this.cooplace = []
for (let i = 0; i < coolplabuf.length; i++) {
coolplabuf[i][2].returnco()
}
}
Etiquettes.prototype.disable = function disable () {
this.parent.removeEventListener('mousemove', this.place2Listener, false)
this.disabled = true
for (let i = 0; i < this.cooplace.length; i++) {
this.cooplace[i][2].disable()
}
}
Etiquettes.prototype.detruit = function detruit () {
this.disable()
j3pDetruit(this.spanContenant)
}
Etiquettes.prototype._handleStart = function _handleStart (evt) {
evt.preventDefault()
const touches = evt.changedTouches
for (let i = 0; i < touches.length; i++) {
this.ongoingTouches.push(touches[i])
}
}
Etiquettes.prototype._handleEnd = function _handleEnd (evt) {
this.ongoingTouches = []
evt.preventDefault()
this.place({ ctrlKey: false })
}
Etiquettes.prototype._handleCancel = function _handleCancel (evt) {
evt.preventDefault()
this.ongoingTouches = []
}
Etiquettes.prototype._handleLeave = function _handleLeave (evt) {
this.ongoingTouches = []
evt.preventDefault()
}
Etiquettes.prototype._handleMove = function _handleMove (evt) {
if (this.disabled || (this.listdivchoix === -1)) return
const ongoingTouchIndexById = (idToFind) => {
for (let i = 0; i < this.ongoingTouches.length; i++) {
const id = this.ongoingTouches[i].identifier
if (id === idToFind) return i
}
return -1 // toucher non trouvé
}
evt.preventDefault()
j3pStyle(this.listdivchoix, { zIndex: 1 })
const touches = evt.changedTouches
for (let i = 0; i < touches.length; i++) {
const idx = ongoingTouchIndexById(touches[i].identifier)
if (idx === -1) continue
this.place2({ clientX: this.ongoingTouches[idx].pageX, clientY: this.ongoingTouches[idx].pageY })
this.ongoingTouches.splice(idx, 1, touches[i]) // mettre à jour la liste des touchers
}
}
export default Etiquettes