import $ from 'jquery'
import { j3pAddElt, j3pChaine, j3pVirgule, j3pEmpty, j3pFocus, j3pPaletteMathquill, j3pMin } from 'src/legacy/core/functions'
import { fctsEtudeEcrireNbLatex, fctsEtudeEstDansDomaine, fctsEtudeOrdonneTabSansDoublon } from 'src/legacy/outils/fonctions/etude'
import { j3pAffiche, mqRestriction } from 'src/lib/mathquill/functions'
import { j3pCreeRectangle, j3pCreeSegment } from 'src/legacy/core/functionsSvg'
import { j3pCalculValeur } from 'src/legacy/core/functionsTarbre'
/**
* Construit le tableau de signes utilisé dans les sections signe_courbe1 et signe_courbe2
* @param {HTMLElement} obj conteneur du tableau
* @param {Object} objParam
* @param {object} [objParam.tab_dimension] tab_dimension[0] est la largeur, tab_dimension[1] la hauteur
* tab_dimension[2] est le nombre de valeurs à ajouter sur l’axe des abscisses (en plus des bornes)
* tab_dimension[3] est un tableau de deux éléments : les bornes les plus extrêmes du domaine de def de la fonction (écrire infini pour \\infty)'
* tab_dimension[4] est un tableau optionnel. S’il n’est pas undefined, c’est le domaine réel de définition sous la forme par exemple ["-infini",a,"]","[",a,"+infini","]","["] pour une valeur interdite
* tab_dimension[5] est un argument optionnel. S’il vaut true, alors on donne la possibilité dans les menus déroulants de mettre une double barre (pour la présence éventuelle de valeurs interdites)
* @param {object} [objParam.zero_tab] tableau de booléens : le 1er vaut true si la 1ère ligne est complétée, le 2ème, vaut true si la 2ème ligne est complétée, le 3ème (optionnel) vaut false si on veut des listes déroulantes
* @param {boolean} [objParam.afficheBornes] qui vaut true si on affiche les bornes au lieu d’y mettre des zones de saisie (utile lorsque zero_tab[0] vaut false)
* @param {object} [objParam.val_zero_tab] tableau de valeurs en lesquelles s’annule la fonction
* @param {object} [objParam.signe_tab_corr] tableau contenant les signes de la fonction
* @param {object} [objParam.obj_style_couleur] peut contenir 4 éléments (les 2 derniers étant obligatoires) : un style de texte, couleur si on ne définit par le style, texte qui sera "signe de ", nom_f
* @param {object} [objParam.palette] argument optionnel qui est un tableau contenant les outils de la palette qu’on souhaite donner à l’élève
* @return {Object} objet {zone, signe, liste, palette} pour récupérer les zones de saisie : zone pour les inputs de la 1ère ligne, signe pour les inputs destinés aux signes et liste pour les listes déroulante (zéro ou barre) et le conteneur de la palette
*/
export function tableauSignesFct (obj, objParam) {
function ecoute (zone, palette) {
if (zone.className.includes('mq-editable-field')) {
j3pEmpty(laPaletteDiv)
j3pPaletteMathquill(laPaletteDiv, zone, { liste: palette })
}
}
// on crée un tableau de signes dans obj
/* objParam contient différentes propriétés destinées à construire ce tableau :
tab_dimension,zero_tab,val_zero_tab,signe_tab_corr,obj_style_couleur,palette */
// ici il ne s’agit que du tableau du signe d’une fonction, pas d’un produit ou quotient
// gestions des choses à afficher (valeurs ou zones de saisie) :
if (typeof (objParam.zero_tab) !== 'object') return console.error('zero_tab doit être un array de booléen')
// Double négation pour convertir en booléen si ce ne l’est pas
const afficheLigneX = !!(objParam.zero_tab[0])
const afficheSignes = !!(objParam.zero_tab[1])
const affiche0Ligne2 = !!(objParam.zero_tab[2])
const laPalette = (objParam.palette === undefined) ? [] : objParam.palette
const nomdiv = obj
const macouleur = (objParam.obj_style_couleur.couleur === undefined) ? objParam.obj_style_couleur.style.color : objParam.obj_style_couleur.couleur
// macouleur = "#000000",
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
const L = objParam.tab_dimension[0]
const h = objParam.tab_dimension[1]
svg.setAttribute('width', L + 1)
svg.setAttribute('height', h + 1)
nomdiv.appendChild(svg)
j3pCreeRectangle(svg, { x: 1, y: 1, width: L - 1, height: h - 1, couleur: macouleur, epaisseur: 1 })
j3pCreeSegment(svg, { x1: 1, y1: 0, x2: 0, y2: h, couleur: macouleur, epaisseur: 1 })
j3pCreeSegment(svg, { x1: 1, y1: h / 2, x2: L, y2: h / 2, couleur: macouleur, epaisseur: 1 })
// placement de la ligne "signe de f"
const styleText = Object.assign({}, objParam.obj_style_couleur.style)
styleText.position = 'absolute'
const signeDe = j3pAddElt(nomdiv, 'div', '', { style: styleText })
// dans la section, il faut que le nom de la fonction apparaisse sous la forme £f
j3pAffiche(signeDe, '', objParam.obj_style_couleur.texte, { f: objParam.obj_style_couleur.nom_f })
// pour placer le segment vertical, je cherche la largeur de la phrase "signe de ..."
const largeurSignede = signeDe.getBoundingClientRect().width + 4
const posTxt = h / 2 + h / 4 - signeDe.getBoundingClientRect().height / 2
j3pCreeSegment(svg, { x1: largeurSignede, y1: 0, x2: largeurSignede, y2: h, couleur: macouleur, epaisseur: 1 })
signeDe.style.top = posTxt + 'px'
signeDe.style.left = '2px'
// placement du "x"
const leX = j3pAddElt(nomdiv, 'div', '', { style: styleText })
j3pAffiche(leX, '', '$x$')
const posTxt2 = h / 4 - leX.getBoundingClientRect().height / 2
const posTxt3 = largeurSignede / 2 - leX.getBoundingClientRect().width / 2
leX.style.top = posTxt2 + 'px'
leX.style.left = posTxt3 + 'px'
let borneInfTxt, borneSupTxt
if (objParam.tab_dimension[3] === undefined) {
borneInfTxt = '$-\\infty$'
borneSupTxt = '$+\\infty$'
} else {
if ((objParam.tab_dimension[3][0] === undefined) || (objParam.tab_dimension[3][1] === undefined)) {
borneInfTxt = '$-\\infty$'
borneSupTxt = '$+\\infty$'
} else {
if (objParam.tab_dimension[3][0] === '-infini') {
borneInfTxt = '$-\\infty$'
} else {
borneInfTxt = '$' + fctsEtudeEcrireNbLatex(String(objParam.tab_dimension[3][0])) + '$'
}
if (objParam.tab_dimension[3][1] === '+infini') {
borneSupTxt = '$+\\infty$'
} else {
borneSupTxt = '$' + fctsEtudeEcrireNbLatex(String(objParam.tab_dimension[3][1])) + '$'
}
}
}
const zoneInput = []
const signeInput = []
const listeInput = []
if (afficheLigneX || objParam.afficheBornes) {
// on remplit entièrement la première ligne (sans zone de saisie)
// plus et moins l’infini'
const moinsInf = j3pAddElt(nomdiv, 'div', '', { style: styleText })
const plusInf = j3pAddElt(nomdiv, 'div', '', { style: styleText })
// Je n’affiche les bornes que si on affiche toute la première ligne'
j3pAffiche(moinsInf, '', borneInfTxt)
moinsInf.style.left = (largeurSignede + 1) + 'px'
moinsInf.style.top = (h / 4 - moinsInf.getBoundingClientRect().height / 2) + 'px'
j3pAffiche(plusInf, '', borneSupTxt)
plusInf.style.left = (L - plusInf.getBoundingClientRect().width - 2 + 1) + 'px'
plusInf.style.top = (h / 4 - plusInf.getBoundingClientRect().height / 2) + 'px'
}
const tabZeroOrdonne = fctsEtudeOrdonneTabSansDoublon(objParam.val_zero_tab, objParam.tab_dimension[3])
const nbValx = objParam.tab_dimension[2]
// pour gérer les bornes qui peuvent être des zéros ou des valeurs interdites
// on y met soit un zéro, soit une double barre
let newTab4
if (objParam.tab_dimension[4] === undefined) {
newTab4 = objParam.tab_dimension[3]
newTab4.push(']', '[')
} else {
newTab4 = objParam.tab_dimension[4]
}
// dans le cas où on a changé le domaine de def, il faut qu’on regarde si les bornes sont des zéros de la fonction
let tabValZeros = []
let i, j
for (i = 0; i < objParam.val_zero_tab.length; i++) {
tabValZeros = tabValZeros.concat(String(objParam.val_zero_tab[i]).split('|'))
}
if (newTab4[0] !== '-infini') {
for (j = 0; j < tabValZeros.length; j++) {
if (Math.abs(j3pCalculValeur(tabValZeros[j]) - j3pCalculValeur(newTab4[0])) < Math.pow(10, -12)) {
// c’est que la borne inf du domaine est un zéro de la fonction ou une valeur interdite
if (newTab4[newTab4.length - 2] === '[') {
// si c’est un zéro :
const zeroFct = j3pAddElt(nomdiv, 'div', '0', { style: styleText })
zeroFct.style.left = (largeurSignede) + 'px'
zeroFct.style.top = (3 * h / 4 - zeroFct.getBoundingClientRect().height / 2) + 'px'
} else {
// et pour une valeur interdite
j3pCreeSegment(svg, { x1: largeurSignede + 5, y1: h / 2, x2: largeurSignede + 5, y2: h, couleur: macouleur, epaisseur: 1 })
}
}
}
}
if (newTab4[newTab4.length - 3] !== '+infini') {
for (j = 0; j < tabValZeros.length; j++) {
if (Math.abs(j3pCalculValeur(tabValZeros[j]) - j3pCalculValeur(newTab4[newTab4.length - 3])) < Math.pow(10, -12)) {
// c’est que la borne inf du domaine est un zéro de la fonction ou une valeur interdite
if (newTab4[newTab4.length - 1] === ']') {
// si c’est un zéro
const zeroFct = j3pAddElt(nomdiv, 'div', '0', { style: styleText })
zeroFct.style.left = (L - zeroFct.getBoundingClientRect().width - 2 + 1) + 'px'
zeroFct.style.top = (3 * h / 4 - zeroFct.getBoundingClientRect().height / 2) + 'px'
} else {
// et pour une valeur interdite
j3pCreeSegment(svg, { x1: L - 5, y1: h / 2, x2: L - 5, y2: h, couleur: macouleur, epaisseur: 1 })
}
}
}
}
let imin = 0
let imax = nbValx + 1
// Fin de la gestion du zéro aux bornes ou de la valeur interdite
if (afficheLigneX) {
// les endroits où s’annulent la fonction sont donnés
// attention les_zeros doivent être du type string (un entier ou un décimal ou un nb fractionnaire de la forme a/b
// dans un premier temps, on ordonne les nombre du tableau val_zero_tab (qui sont ls endroits où s’annulent notre produit)
// Dans le cas où sont présents la fonction exp, la fonction ln ou la fonction racine, il va falloir gérer l’affichage'
for (const [i, nb] of tabZeroOrdonne.entries()) {
const leZero = /frac/.test(nb) ? nb : j3pVirgule(nb) // nb est une string ou un nombre
const monZeroTxt = fctsEtudeEcrireNbLatex(leZero)
const zoneNulle = j3pAddElt(nomdiv, 'div', '', { style: styleText })
j3pAffiche(zoneNulle, '', '$' + monZeroTxt + '$')
zoneNulle.style.left = (largeurSignede + (i + 1) * (L - largeurSignede) / (nbValx + 1) - zoneNulle.getBoundingClientRect().width / 2) + 'px'
zoneNulle.style.top = (h / 4 - zoneNulle.getBoundingClientRect().height / 2) + 'px'
}
} else {
// dans le cas où les valeur en lesquelles s’annule le produit sont à donner
if (objParam.afficheBornes) imin = 1
if (objParam.afficheBornes) imax = nbValx
for (i = imin; i <= imax; i++) {
// i==0 pour la borne inf du domaine et i==val_x+1 pour la borne_sup du domaine
const zoneNulle = j3pAddElt(nomdiv, 'div', '', { style: styleText })
const elt = j3pAffiche(zoneNulle, '', '&1&', { inputmq1: { texte: '' } })
zoneInput.push(elt.inputmqList[0])
elt.inputmqList[0].leSpan = elt.parent.parentNode
elt.inputmqList[0].num = i
// suivant la palette d’outils, on peut autoriser plus ou moins de touches du clavier
let toucheRestriction = '\\d,.+-'
if (laPalette.length > 0) {
// on peut en ajouter dans ce cas
if (laPalette.includes('fraction')) { toucheRestriction += '/' }
if (laPalette.includes('puissance')) { toucheRestriction += '\\^' }
}
mqRestriction(elt.inputmqList[0], toucheRestriction, { commandes: laPalette })
if (i === 0) {
// placement de la borne inf
zoneNulle.style.left = (largeurSignede + 2) + 'px'
} else if (i === (nbValx + 1)) {
// placement de la borne sup
zoneNulle.style.left = (L - 5 - zoneNulle.getBoundingClientRect().width) + 'px'
} else {
zoneNulle.style.left = (largeurSignede + i * (L - largeurSignede) / (nbValx + 1) - zoneNulle.getBoundingClientRect().width / 2) + 'px'
}
zoneNulle.style.top = (h / 4 - zoneNulle.getBoundingClientRect().height / 2) + 'px'
}
for (i = 0; i < zoneInput.length; i++) {
zoneInput[i].addEventListener('input', function () {
if (this.num === 0) {
this.leSpan.style.left = (largeurSignede + 2) + 'px'
} else if (this.num === nbValx + 1) {
this.leSpan.style.left = (L - 10 - this.getBoundingClientRect().width) + 'px'
} else {
this.leSpan.style.left = (largeurSignede + this.num * (L - largeurSignede) / (nbValx + 1) - this.getBoundingClientRect().width / 2) + 'px'
}
this.leSpan.style.top = (h / 4 - this.getBoundingClientRect().height / 2) + 'px'
})
}
}
// on crée tout d’abord les segments verticaux
const posValZero = []
for (i = 1; i <= nbValx; i++) {
posValZero[i] = largeurSignede + i * (L - largeurSignede) / (nbValx + 1)
j3pCreeSegment(svg, { x1: posValZero[i], y1: h / 2, x2: posValZero[i], y2: h, couleur: macouleur, epaisseur: 1 })
}
if (afficheSignes) {
// on donne le signe de la fonction
// les signes
for (i = 1; i <= nbValx + 1; i++) {
const leSigneFct = j3pAddElt(nomdiv, 'div', '', { style: styleText })
j3pAffiche(leSigneFct, '', '$' + objParam.signe_tab_corr[i - 1] + '$')
leSigneFct.style.left = largeurSignede + (i - 1 / 2) * (L - largeurSignede) / (nbValx + 1) - leSigneFct.getBoundingClientRect().width / 2 + 'px'
leSigneFct.style.top = 3 * h / 4 - leSigneFct.getBoundingClientRect().height / 2 + 'px'
}
} else {
// le signe de la fonction est à compléter
// emplacement pour le premier signe
for (i = 1; i <= nbValx + 1; i++) {
const leSigneFct = j3pAddElt(nomdiv, 'div', '', { style: styleText })
const elt = j3pAffiche(leSigneFct, '', '&1&', { inputmq1: { texte: '' } })
signeInput.push(elt.inputmqList[0])
elt.inputmqList[0].leSpan = elt.parent.parentNode
elt.inputmqList[0].num = i
leSigneFct.leContenu = ''// cette variable va me permettre d’identifier le contenu pour l’emp^cher d’avoir plus d’un caractère
mqRestriction(elt.inputmqList[0], '+-')
elt.inputmqList[0].addEventListener('keypress', function () {
this.leContenu = $(this).mathquill('latex')
})
elt.inputmqList[0].addEventListener('keyup', function () {
const newContenu = $(this).mathquill('latex')
this.leContenu = newContenu[0]
if ((this.leContenu !== '+') && (this.leContenu !== '-')) {
this.leContenu = ''
}
$(this).mathquill('latex', this.leContenu)
$(this).focus() // pour passer sans encombre à sesaparcours, j’ai dû le mettre sur 2 lignes
})
leSigneFct.style.left = (largeurSignede + (2 * i - 1) * (L - largeurSignede) / (2 * (nbValx + 1)) - elt.inputmqList[0].getBoundingClientRect().width / 2) + 'px'
leSigneFct.style.top = (3 * h / 4 - elt.inputmqList[0].getBoundingClientRect().height / 2) + 'px'
}
// ajustement de la position de chaque signe
for (i = 1; i <= nbValx + 1; i++) {
signeInput[i - 1].addEventListener('input', function () {
this.leSpan.style.left = (largeurSignede + (2 * this.num - 1) * (L - largeurSignede) / (2 * nbValx + 2) - this.getBoundingClientRect().width / 2) + 'px'
this.leSpan.style.top = (3 * h / 4 - this.getBoundingClientRect().height / 2) + 'px'
})
}
if (imin > imax) j3pFocus(signeInput[0])
}
if (affiche0Ligne2) {
// les zéros à la place de la liste déroulante
for (i = 1; i <= nbValx; i++) {
const afficheZero = !tabZeroOrdonne[i - 1] || fctsEtudeEstDansDomaine(tabZeroOrdonne[i - 1], newTab4)
// !tabZeroOrdonne[i - 1] est utile car cela se produit quand on a des zones de saisie (qui ne correspond plus nécessairement à un zéro de la fonction)
// du coup tabZeroOrdonne[i - 1] peut être undefined. Dans ce cas, on lui met un 0 dessous
if (afficheZero) {
const leZero = j3pAddElt(nomdiv, 'div', '0', { style: styleText })
leZero.style.left = (largeurSignede + i * (L - largeurSignede) / (nbValx + 1) - leZero.getBoundingClientRect().width / 2) + 'px'
leZero.style.top = (3 * h / 4 - leZero.getBoundingClientRect().height / 2) + 'px'
} else {
j3pCreeSegment(svg, { x1: largeurSignede + i * (L - largeurSignede) / (nbValx + 1) + 3, y1: h / 2, x2: largeurSignede + i * (L - largeurSignede) / (nbValx + 1) + 3, y2: h, couleur: objParam.obj_style_couleur.couleur, epaisseur: 1 })
j3pCreeSegment(svg, { x1: largeurSignede + i * (L - largeurSignede) / (nbValx + 1), y1: h / 2, x2: largeurSignede + i * (L - largeurSignede) / (nbValx + 1), y2: h, couleur: objParam.obj_style_couleur.couleur, epaisseur: 1 })
}
}
} else {
// liste déroulante
for (i = 1; i <= nbValx; i++) {
const laListe = j3pAddElt(nomdiv, 'div', '', { style: styleText })
const tabTextListe = (objParam.tab_dimension[5]) ? ['|', '||', '0'] : ['|', '0']
const elt = j3pAffiche(laListe, '', '#1#', { liste1: { texte: tabTextListe }, className: 'liste1' })
listeInput.push(elt.selectList[0])
laListe.style.left = (largeurSignede + i * (L - largeurSignede) / (nbValx + 1) - 8) + 'px'
laListe.style.top = (3 * h / 4 - laListe.getBoundingClientRect().height / 2) + 'px'
}
}
// affichage d’une palette pour compléter les zones de la première ligne
let laPaletteDiv
if (!afficheLigneX && (laPalette.length > 0)) {
// ceci ne se fait que si la première ligne n’est pas complétée
laPaletteDiv = j3pAddElt(nomdiv, 'div')
// palette MQ :
j3pPaletteMathquill(laPaletteDiv, zoneInput[0], { liste: laPalette, position: { top: h, left: 5 } })
for (i = 0; i <= nbValx + 1; i++) {
$(zoneInput[i]).focusin(function () {
ecoute(this, objParam.palette)
})
}
for (i = 1; i <= (nbValx + 1) * (tabZeroOrdonne.length + 1); i++) {
$(signeInput[i - 1]).focusin(function () {
j3pEmpty(laPaletteDiv)
})
}
for (i = 1; i <= (nbValx) * (tabZeroOrdonne.length + 1); i++) {
$(listeInput[i - 1]).focusin(function () {
j3pEmpty(laPaletteDiv)
})
}
}
if (afficheLigneX) {
if (!afficheSignes) j3pFocus(signeInput[0])
} else {
if (imin <= imax) j3pFocus(zoneInput[0])
else if (!afficheSignes) j3pFocus(signeInput[0])
}
return { zone: zoneInput, signe: signeInput, liste: listeInput, palette: laPaletteDiv }
}
/**
* Construit le tableau de signes utilisé dans les sections signe_courbe1 et signe_courbe2
* @param {HTMLElement} obj conteneur du tableau
* @param {Object} objParam
* @param {string} [objParam.nomFct] pour le nom de la fonction qui sera écrit dans "signe de f(x)" - 'f' par défaut
* @param {number} [objParam.L] largeur du tableau
* @param {number} [objParam.h] hauteur du tableau
* @param {object} [objParam.tabZero] tableau des zéros de la fonction
* @param {object} [objParam.tabValInterdite] tableau des valeurs interdites de la fonction
* @param {object} [objParam.tabSignes] tableau contenant les signes de la fonction
* @param {object} [objParam.eltsAffiches] tableau de 3 booléens : le 1er pour savoir si on écrit les abscisses, le 2ème, pour les zéros et/ou double barre et le 3ème pour les signes
* @param {Object} [objParam.styleTxt] style du texte
* @return {Object} objet {zone, signe, liste} pour récupérer les zones de saisie : zone pour les inputs de la 1ère ligne, signe pour les inputs destinés aux signes et liste pour les listes déroulante (zéro ou barre)
*/
export function construireTableauSignes (obj, objParam) {
// on crée un tableau de signes dans obj
// dans le tableau, on écrira 'signe de nomFct(x)'
// tabZero est un tableau contenant la liste des valeurs en la(les)quelle(s) s’annule la fonction
// ce tableau est vide si la fonction ne s’annule pas'
// ce tableau contient aussi les éventuelles valeurs interdites
// objParam.tabValInterdite est un tableau de booleens objParam.tabValInterdite[i] vaut true si tabZero[i] est une valeur interdite
// zerosAffiches est un booléen : il permet de faire en sorte que la première ligne soit complète ou avec des zones de saisie
// tabSignes est le tableau contenant le signe de la fonction (utile pour une utlisation comme correction)
// styleTxt est le style du texte. On en extrait la couleur pour la couleur du tableau
// eltsAffiches est un tableau contenant 3 booléens :
const tabZero = objParam.tabZero
const zerosAffiches = objParam.eltsAffiches[0]// il permet de faire en sorte que la première ligne soit complète ou avec des zones de saisie
const zerosBarresAffiches = objParam.eltsAffiches[1]// il permet de savoior si on affiche le zéro ou la double barre das la deuxième ligne du tableau
const signesAffiches = objParam.eltsAffiches[2]// il vaut true pour afficher les signes (pour la correction)
const styleText = Object.assign({}, objParam.styleTxt)
const debug = objParam.debug
const signeDeTxt = j3pChaine(objParam.signeDeTxt, { f: ((objParam.nomFct) ? objParam.nomFct : 'f') + '(x)' })
styleText.position = 'absolute'
const nomdiv = obj
const h = (objParam.h) ? objParam.h : 100
const L = (objParam.L) ? objParam.L : 420
const txt2Txt = '<p>' + signeDeTxt + '</p>'
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
svg.setAttribute('width', L + 2)
svg.setAttribute('height', h + 1)
nomdiv.appendChild(svg)
j3pCreeRectangle(svg, { x: 1, y: 0, width: L - 1, height: h, couleur: '#000000', epaisseur: 1 })
j3pCreeSegment(svg, { x1: 1, y1: 0, x2: 0, y2: h, couleur: '#000000', epaisseur: 1 })
j3pCreeSegment(svg, { x1: 1, y1: h / 2.5, x2: L, y2: h / 2.5, couleur: '#000000', epaisseur: 1 })
// placement de la ligne "signe de ax+b"
const signeDe = j3pAddElt(nomdiv, 'div', '', { style: styleText })
j3pAffiche(signeDe, '', txt2Txt)
// pour placer le segment vertical, je cherche la largeur de la phrase "signe de ..."
const largeurSigneDe = signeDe.getBoundingClientRect().width + 4
j3pCreeSegment(svg, { x1: largeurSigneDe, y1: 0, x2: largeurSigneDe, y2: h, couleur: '#000000', epaisseur: 1 })
const posTxt = h / 2.5 + 3 * h / 10 - signeDe.getBoundingClientRect().height / 2
signeDe.style.top = posTxt + 'px'
signeDe.style.left = '2px'
// placement du "x"
const leX = j3pAddElt(nomdiv, 'div', '', { style: styleText })
j3pAffiche(leX, '', '$x$')
const posTxt2 = h / 5 - leX.getBoundingClientRect().height / 2
leX.style.top = posTxt2 + 'px'
const posTxt3 = largeurSigneDe / 2 - leX.getBoundingClientRect().width / 2
leX.style.left = posTxt3 + 'px'
// plus et moins l’infini'
const moinsInf = j3pAddElt(nomdiv, 'div', '', { style: styleText })
const plusInf = j3pAddElt(nomdiv, 'div', '', { style: styleText })
j3pAffiche(moinsInf, '', '$-\\infty$')
moinsInf.style.left = (largeurSigneDe + 1) + 'px'
moinsInf.style.top = (h / 5 - moinsInf.getBoundingClientRect().height / 2) + 'px'
j3pAffiche(plusInf, '', '$+\\infty$')
plusInf.style.left = (L - plusInf.getBoundingClientRect().width - 2 + 1) + 'px'
plusInf.style.top = (h / 5 - plusInf.getBoundingClientRect().height / 2) + 'px'
const tabAbscisses = tabZero.concat(objParam.tabValInterdite)
if (debug) console.debug('tabAbscisses : ' + tabAbscisses)
const tabAbscissesApproche = []
// ce tableau contient les valeurs de tabAbscisses pour lesquelles on remplace une fraction par une valeur arrondie
for (let i = 0; i < tabAbscisses.length; i++) {
const leZero = j3pVirgule(tabAbscisses[i])
if (leZero.includes('/')) {
tabAbscissesApproche[i] = Number(leZero.split('/')[0]) / Number(leZero.split('/')[1])
} else {
tabAbscissesApproche[i] = Number(leZero)
}
}
let zeroInit = []
zeroInit = zeroInit.concat(tabAbscissesApproche)
const tabAbscissesOrdonne1 = []
for (let i = 0; i < tabAbscissesApproche.length; i++) {
const objMin = j3pMin(zeroInit)
tabAbscissesOrdonne1[i] = objMin.min
zeroInit.splice(objMin.indice, 1)
}
const tabAbscissesOrdonne2 = []
const tabAbscissesOrdonneLatex = []
for (let i = 0; i < tabAbscisses.length; i++) {
const index = tabAbscissesApproche.indexOf(tabAbscissesOrdonne1[i])
tabAbscissesOrdonne2[i] = tabAbscisses[index]
const leZero = j3pVirgule(tabAbscissesOrdonne2[i])
if (leZero.includes('/')) {
tabAbscissesOrdonneLatex[i] = '\\frac{' + leZero.split('/')[0] + '}{' + leZero.split('/')[1] + '}'
} else {
tabAbscissesOrdonneLatex[i] = leZero
}
}
if (debug) console.debug('tabAbscissesOrdonne2:' + tabAbscissesOrdonne2 + ' tabAbscissesOrdonneLatex:' + tabAbscissesOrdonneLatex)
const zoneInput = []
const signeInput = []
const listeInput = []
for (let i = 0; i < tabAbscissesOrdonne2.length; i++) {
const abscisse = j3pAddElt(nomdiv, 'div', '', { style: styleText })
if (zerosAffiches) {
// on écrit les abscisses
j3pAffiche(abscisse, '', '$' + tabAbscissesOrdonneLatex[i] + '$')
abscisse.style.left = (largeurSigneDe + (i + 1) * (L - largeurSigneDe) / (tabAbscissesOrdonne2.length + 1) - abscisse.getBoundingClientRect().width / 2) + 'px'
if (tabAbscissesOrdonneLatex[i].includes('frac')) {
abscisse.style.top = (h / 6.5 - abscisse.getBoundingClientRect().height / 2) + 'px'
} else {
abscisse.style.top = (h / 5 - abscisse.getBoundingClientRect().height / 2) + 'px'
}
} else {
// on met des zones de saisie à la place des abscisses
const elt = j3pAffiche(abscisse, '', '&1&', { inputmq1: { texte: '' } })
zoneInput.push(elt.inputmqList[0])
elt.inputmqList[0].leSpan = elt.parent.parentNode
elt.inputmqList[0].num = i
abscisse.style.left = (largeurSigneDe + (i + 1) * (L - largeurSigneDe) / (tabAbscissesOrdonne2.length + 1) - elt.inputmqList[0].getBoundingClientRect().width / 2) + 'px'
abscisse.style.top = (h / 5 - elt.inputmqList[0].getBoundingClientRect().height / 2) + 'px'
elt.inputmqList[0].addEventListener('input', function () {
this.leSpan.style.left = (largeurSigneDe + (this.num + 1) * (L - largeurSigneDe) / (tabAbscissesOrdonne2.length + 1) - this.getBoundingClientRect().width / 2) + 'px'
this.leSpan.style.top = (h / 5 - this.getBoundingClientRect().height / 2) + 'px'
})
mqRestriction(elt.inputmqList[0], '\\d.,/\\-')
}
// pour les doubles barres ou les zéros
j3pCreeSegment(svg, { x1: largeurSigneDe + (i + 1) * (L - largeurSigneDe) / (tabAbscissesOrdonne2.length + 1), y1: h / 2.5, x2: largeurSigneDe + (i + 1) * (L - largeurSigneDe) / (tabAbscissesOrdonne2.length + 1), y2: h, couleur: styleText.color, epaisseur: 1 })
if (zerosBarresAffiches) {
// on les affiche
if (tabZero.includes(tabAbscissesOrdonne2[i])) {
// on écrit un zéro et non une double barre
const zeroBarre = j3pAddElt(nomdiv, 'div', '', { style: styleText })
j3pAffiche(zeroBarre, '', '0')
zeroBarre.style.left = largeurSigneDe + (i + 1) * (L - largeurSigneDe) / (tabAbscissesOrdonne2.length + 1) - zeroBarre.getBoundingClientRect().width / 2 + 'px'
zeroBarre.style.top = h / 2.5 + 3 * h / 10 - zeroBarre.getBoundingClientRect().height / 2 + 'px'
} else {
// on écrit une double barre
j3pCreeSegment(svg, { x1: largeurSigneDe + (i + 1) * (L - largeurSigneDe) / (tabAbscissesOrdonne2.length + 1) + 3, y1: h / 2.5, x2: largeurSigneDe + (i + 1) * (L - largeurSigneDe) / (tabAbscissesOrdonne2.length + 1) + 3, y2: h, couleur: styleText.color, epaisseur: 1 })
}
} else {
const laListe = j3pAddElt(nomdiv, 'div', '', { style: styleText })
const tabTextListe = ['', '|', '||', '0']
const elt = j3pAffiche(laListe, '', '#1#', { liste1: { texte: tabTextListe } })
listeInput.push(elt.selectList[0])
laListe.style.left = (largeurSigneDe + (i + 1) * (L - largeurSigneDe) / (tabAbscissesOrdonne2.length + 1) - 8) + 'px'
laListe.style.top = (h / 2.5 + 3 * h / 10 - laListe.getBoundingClientRect().height / 2) + 'px'
}
}
for (let i = 0; i < tabAbscissesOrdonne2.length + 1; i++) {
const leSigne = j3pAddElt(nomdiv, 'div', '', { style: styleText })
if (signesAffiches) {
j3pAffiche(leSigne, '', '$' + objParam.tabSignes[i] + '$')
leSigne.style.left = (largeurSigneDe + (i + 0.5) * (L - largeurSigneDe) / (tabAbscissesOrdonne2.length + 1) - leSigne.getBoundingClientRect().width / 2) + 'px'
leSigne.style.top = (h / 2.5 + 3 * h / 10 - leSigne.getBoundingClientRect().height / 2) + 'px'
} else {
const elt = j3pAffiche(leSigne, '', '&1&', { inputmq1: { texte: '' } })
signeInput.push(elt.inputmqList[0])
const lengthTab = tabAbscissesOrdonne2.length
leSigne.style.left = (largeurSigneDe + (i + 0.5) * (L - largeurSigneDe) / (lengthTab + 1) - leSigne.getBoundingClientRect().width / 2) + 'px'
leSigne.style.top = (h / 2.5 + 3 * h / 10 - leSigne.getBoundingClientRect().height / 2) + 'px'
mqRestriction(elt.inputmqList[0], '+\\-')
elt.inputmqList[0].leSpan = elt.parent.parentNode
elt.inputmqList[0].num = i
elt.inputmqList[0].addEventListener('input', function () {
this.leSpan.style.left = (largeurSigneDe + (this.num + 0.5) * (L - largeurSigneDe) / (lengthTab + 1) - this.getBoundingClientRect().width / 2) + 'px'
this.leSpan.style.top = (h / 2.5 + 3 * h / 10 - this.getBoundingClientRect().height / 2) + 'px'
})
}
}
if (!zerosAffiches) {
j3pFocus(zoneInput[0])
} else if (!signesAffiches) {
j3pFocus(signeInput[0])
}
return { zone: zoneInput, signe: signeInput, liste: listeInput }
}