import { j3pAddElt, j3pElement, j3pIsHtmlElement } from 'src/legacy/core/functions'
import './table.scss'
/** @module legacy/themes/table */
/**
* Ajoute un tag table avec ses tr & td dans container
* @param {HTMLElement|string} container
* @param {Object} opts
* @param {number} opts.nbLignes
* @param {number} opts.nbColonnes
* @param {string} [opts.id] si fourni cet id sera mis sur le tag table,
* les tr auront cet id avec en suffixe lY (où Y est l’index de la ligne, qui démarre donc à 0)
* et les td auront l’id de la ligne avec en suffixe cX où X est l’index de la colonne
* @param {string} [opts.className] éventuelle classe css à appliquer au tableau (cf table.scss pour la liste des styles connus par ce modèle, tbDefault|tbWithBorder)
* @param {Array[]} [opts.contents] contenus éventuels à mettre dans les tag td
* @param {boolean} [opts.withHeader=false] Passer true pour que les cellules de la première ligne soient des <th> et pas des <td>
* @return {HTMLTableElement}
*/
export function addTable (container, opts) {
if (!Number.isInteger(opts?.nbLignes) || !Number.isInteger(opts?.nbColonnes) || opts.nbLignes < 0 || opts.nbColonnes < 0) throw Error('Arguments invalides')
const { id, nbLignes, nbColonnes, className, withHeader } = opts
const tableProps = { className, id }
// on vérifie quand même que l’id n’existe pas dans le dom
if (id && j3pElement(id, false)) delete tableProps.id // j3pElement a déjà râlé, on ajoute rien, on vire juste l’id déjà existant
if (className === undefined) tableProps.className = 'tbDefault'
const table = j3pAddElt(container, 'table', '', tableProps)
const contents = Array.isArray(opts.contents) ? opts.contents : []
while (table.childNodes.length < nbLignes) {
const iLig = table.childNodes.length
const tr = j3pAddElt(table, 'tr')
if (id) tr.id = `${id}l${iLig}`
const cellTag = (iLig === 0 && withHeader) ? 'th' : 'td'
while (tr.childNodes.length < nbColonnes) {
const iCol = tr.childNodes.length
const content = (Array.isArray(contents[iLig]) && contents[iLig][iCol]) || ''
const tdProps = {}
if (id) tdProps.id = `${id}l${iLig}c${iCol}`
j3pAddElt(tr, cellTag, content, tdProps)
}
}
return table
}
/**
* Ajoute un tableau et retourne ses cellules (pas l’élément table)
* @param {HTMLElement|string} container
* @param {number} nbLignes
* @param {number} nbColonnes
* @return {TableCells}
*/
export function addDefaultTable (container, nbLignes, nbColonnes) {
const table = addTable(container, { className: 'tbDefault', nbLignes, nbColonnes })
return getCells(table)
}
/**
* Retourne un tableau de tableaux de tous les td de table
* @param {HTMLTableElement} table
* @return {TableCells}
*/
export function getCells (table) {
if (!j3pIsHtmlElement(table)) throw Error('argument invalide')
// on retourne pour chaque tr trouvé dans table la liste des td qu’il contient
// attention, querySelectorAll retourne une NodeList qui n’a pas de méthode map, d’où Array.from
// le :scope sert à désigner l’élément sur lequel on est appelé, pour ne prendre ici que ses enfants directs
// (au cas où le <table> en contiendrait d’autres on veut pas toute la descendance
// cf https://developer.mozilla.org/fr/docs/Web/API/Document/querySelectorAll#notes
return Array.from(table.querySelectorAll(':scope > tr')) // tableau de ligne
.map(tr => Array.from(tr.querySelectorAll(':scope > td'))) // pour chaque elt de la ligne on retourne le tableau des td qu’elle contient
}
export function getLines (table) {
if (!j3pIsHtmlElement(table)) throw Error('argument invalide')
// on retourne pour chaque tr trouvé dans table la liste des td qu’il contient
// attention, querySelectorAll retourne une NodeList qui n’a pas de méthode map, d’où Array.from
// le :scope sert à désigner l’élément sur lequel on est appelé, pour ne prendre ici que ses enfants directs
// (au cas où le <table> en contiendrait d’autres on veut pas toute la descendance
// cf https://developer.mozilla.org/fr/docs/Web/API/Document/querySelectorAll#notes
return Array.from(table.querySelectorAll(':scope > tr')) // tableau de lignes
}
/**
* Idem addDefaultTable mais retourne aussi l’élément table et la liste des tr
* @param container
* @param nbLignes
* @param nbColonnes
* @return {{cells: TableCells, lines: HTMLTableRowElement[], table: HTMLTableElement}}
*/
export function addDefaultTableDetailed (container, nbLignes, nbColonnes) {
const table = addTable(container, { className: 'tbDefault', nbLignes, nbColonnes })
return {
cells: getCells(table),
lines: getLines(table),
table
}
}
export function addDefaultTableGrid (where, nbLignes, nbColonnes) {
where.style.display = 'grid'
where.style.gridTemplateColumns = 'repeat(' + nbColonnes + ', auto)'
where.style.gridTemplateRows = 'repeat(' + nbLignes + ', auto)'
where.style.display = 'grid'
const aret = []
for (let i = 0; i < nbLignes; i++) {
aret[i] = []
for (let j = 0; j < nbColonnes; j++) {
const lacase = j3pAddElt(where, 'div')
lacase.style.gridColumn = (j + 1)
lacase.style.gridRow = i
lacase.style.display = 'flex'
lacase.style.alignItems = 'center'
lacase.style.justifyContent = 'center'
lacase.style.textAlign = 'center'
aret[i].push(lacase)
}
}
aret.ligne = nbLignes
aret.co = nbColonnes
aret.where = where
return aret
}
/**
* @typedef LineCells
* @type {HTMLTableDataCellElement[]}
*/
/**
* @typedef TableCells
* @type {LinesCells[]}
*/