Spaces:
Sleeping
Sleeping
// ============================================================================= | |
// FONCTIONS UTILITAIRES POUR LA GESTION DES ÉLÉMENTS | |
// ============================================================================= | |
/** | |
* Active/désactive des éléments par leurs IDs | |
* @param {string[]} elementIds - Liste des IDs des éléments à activer | |
* @param {boolean} enabled - true pour activer, false pour désactiver | |
*/ | |
function toggleElementsEnabled(elementIds, enabled = true) { | |
elementIds.forEach(id => { | |
const element = document.getElementById(id); | |
if (element) { | |
if (enabled) { | |
element.removeAttribute('disabled'); | |
} else { | |
element.setAttribute('disabled', 'true'); | |
} | |
} | |
}); | |
} | |
/** | |
* Affiche/masque des conteneurs par leurs IDs | |
* @param {string[]} containerIds - Liste des IDs des conteneurs à afficher | |
* @param {boolean} visible - true pour afficher, false pour masquer | |
*/ | |
function toggleContainersVisibility(containerIds, visible = true) { | |
containerIds.forEach(id => { | |
const container = document.getElementById(id); | |
if (container) { | |
if (visible) { | |
container.classList.remove('hidden'); | |
} else { | |
container.classList.add('hidden'); | |
} | |
} | |
}); | |
} | |
/** | |
* Affiche le loading overlay avec un message personnalisé | |
* @param {string} message - Message à afficher | |
*/ | |
function showLoadingOverlay(message = 'Chargement en cours...') { | |
document.getElementById('progress-text').textContent = message; | |
toggleContainersVisibility(['loading-overlay'], true); | |
} | |
/** | |
* Masque le loading overlay | |
*/ | |
function hideLoadingOverlay() { | |
toggleContainersVisibility(['loading-overlay'], false); | |
} | |
/** | |
* Réinitialise un select et ajoute des options | |
* @param {string} selectId - ID du select | |
* @param {Object} options - Objet avec les options {value: text} | |
* @param {string} defaultText - Texte par défaut | |
*/ | |
function populateSelect(selectId, options, defaultText = 'Sélectionner...') { | |
const select = document.getElementById(selectId); | |
if (select) { | |
select.innerHTML = `<option value="">${defaultText}</option>`; | |
Object.entries(options).forEach(([text, value]) => { | |
const option = document.createElement('option'); | |
option.value = value; | |
option.textContent = text; | |
select.appendChild(option); | |
}); | |
} | |
} | |
function populateCheckboxDropdown(optionsContainerId, options, filterType, labelId, selectionSet) { | |
const container = document.getElementById(optionsContainerId); | |
container.innerHTML = ''; | |
selectionSet.clear(); // reset all | |
// Ajoute chaque option | |
options.forEach(option => { | |
const safeId = `${filterType}-${encodeURIComponent(option).replace(/[%\s]/g, '_')}`; | |
const label = document.createElement('label'); | |
label.className = "flex items-center gap-2 cursor-pointer py-1"; | |
label.innerHTML = ` | |
<input type="checkbox" class="${filterType}-checkbox option-checkbox" id="${safeId}" value="${option}"> | |
<span>${option}</span> | |
`; | |
label.querySelector('input').addEventListener('change', function () { | |
if (this.checked) { | |
selectionSet.add(this.value); | |
} else { | |
selectionSet.delete(this.value); | |
} | |
// Gestion du label "Tous" | |
updateCheckboxDropdownLabel(filterType, labelId, selectionSet, options.length); | |
// Gestion du "Tous" global | |
const allBox = document.querySelector(`.${filterType}-checkbox[value="all"]`); | |
if (allBox && allBox.checked) allBox.checked = false; | |
// Si plus rien n'est coché, recoche "Tous" | |
if (selectionSet.size === 0 && allBox) allBox.checked = true; | |
applyFilters(); | |
}); | |
container.appendChild(label); | |
}); | |
// Réinitialise le label | |
updateCheckboxDropdownLabel(filterType, labelId, selectionSet, options.length); | |
// Gestion de "Tous" | |
const allBox = document.querySelector(`.${filterType}-checkbox[value="all"]`); | |
if (allBox) { | |
allBox.addEventListener('change', function () { | |
if (this.checked) { | |
// Décoche tout le reste | |
selectionSet.clear(); | |
container.querySelectorAll('input[type="checkbox"]').forEach(cb => cb.checked = false); | |
this.checked = true; // reste coché | |
updateCheckboxDropdownLabel(filterType, labelId, selectionSet, options.length); | |
applyFilters(); | |
} | |
}); | |
} | |
} | |
function updateCheckboxDropdownLabel(type, labelId, set, totalCount) { | |
const label = document.getElementById(labelId); | |
if (!set.size) { | |
label.textContent = type.charAt(0).toUpperCase() + type.slice(1) + " (Tous)"; | |
} else if (set.size === 1) { | |
label.textContent = [...set][0]; | |
} else { | |
label.textContent = `${type.charAt(0).toUpperCase() + type.slice(1)} (${set.size}/${totalCount})`; | |
} | |
} | |
function updateSelectedFilters(filterType, value, isChecked) { | |
if (isChecked) { | |
selectedFilters[filterType].add(value); | |
} else { | |
selectedFilters[filterType].delete(value); | |
} | |
} | |
function populateDaisyDropdown(menuId, options, labelId, onSelect) { | |
const menu = document.getElementById(menuId); | |
menu.innerHTML = ''; | |
// Option "Tous" | |
const liAll = document.createElement('li'); | |
liAll.innerHTML = `<a data-value="">Tous</a>`; | |
liAll.querySelector('a').onclick = e => { | |
e.preventDefault(); | |
document.getElementById(labelId).textContent = "Type"; | |
onSelect(""); | |
}; | |
menu.appendChild(liAll); | |
// Ajoute chaque option | |
options.forEach(opt => { | |
const li = document.createElement('li'); | |
li.innerHTML = `<a data-value="${opt}">${opt}</a>`; | |
li.querySelector('a').onclick = e => { | |
e.preventDefault(); | |
document.getElementById(labelId).textContent = opt; | |
onSelect(opt); | |
}; | |
menu.appendChild(li); | |
}); | |
} | |
function updateFilterLabel(filterType) { | |
const selectedCount = selectedFilters[filterType].size; | |
const labelElement = document.getElementById(`${filterType}-filter-label`); | |
if (selectedCount === 0) { | |
labelElement.textContent = `${filterType} (Tous)`; | |
} else { | |
labelElement.textContent = `${filterType} (${selectedCount} sélectionné${selectedCount > 1 ? 's' : ''})`; | |
} | |
} | |
/** | |
* Extrait les données du tableau selon un mapping | |
* @param {Object} mapping - Mapping des colonnes {columnName: propertyName} | |
* @returns {Array} Données extraites | |
*/ | |
function extractTableData(mapping) { | |
const tbody = document.querySelector('#data-table tbody'); | |
const rows = tbody.querySelectorAll('tr'); | |
const data = []; | |
rows.forEach(row => { | |
const checkboxes = row.querySelectorAll('input[type="checkbox"]:checked'); | |
if (checkboxes.length > 0) { | |
const rowData = {}; | |
Object.entries(mapping).forEach(([columnName, propertyName]) => { | |
const cell = row.querySelector(`td[data-column="${columnName}"]`); | |
if (cell) { | |
if (columnName == "URL") { | |
rowData[propertyName] = cell.querySelector('a').getAttribute('href'); | |
} else { | |
rowData[propertyName] = cell.textContent.trim(); | |
} | |
} | |
}); | |
data.push(rowData); | |
} | |
}); | |
return data; | |
} | |
const TABS = { | |
'doc-table-tab': 'doc-table-tab-contents', | |
'requirements-tab': 'requirements-tab-contents', | |
'solutions-tab': 'solutions-tab-contents', | |
'query-tab': 'query-tab-contents' | |
}; | |
/** | |
* Bascule l'affichage sur le nouveau tab | |
* @param {*} newTab | |
*/ | |
function switchTab(newTab) { | |
// Remove active tab style from all tabs | |
Object.keys(TABS).forEach(tabId => { | |
const tabElement = document.getElementById(tabId); | |
if (tabElement) { | |
tabElement.classList.remove("tab-active"); | |
} | |
}); | |
// Hide all tab contents | |
Object.values(TABS).forEach(contentId => { | |
const contentElement = document.getElementById(contentId); | |
if (contentElement) { | |
contentElement.classList.add("hidden"); | |
} | |
}); | |
// Activate the new tab if it exists in the mapping | |
if (newTab in TABS) { | |
const newTabElement = document.getElementById(newTab); | |
const newContentElement = document.getElementById(TABS[newTab]); | |
if (newTabElement) newTabElement.classList.add("tab-active"); | |
if (newContentElement) newContentElement.classList.remove("hidden"); | |
} | |
} | |
/** | |
* Bascule l'affichage vers la tab uniquement si les requirements sont | |
*/ | |
function enableTabSwitching() { | |
Object.keys(TABS).forEach(tabId => { | |
const tab = document.getElementById(tabId); | |
if (tab) | |
tab.classList.remove("tab-disabled"); | |
}) | |
} | |
/** | |
* Change l'état d'activation du number box de choix de nb de catégories. | |
*/ | |
function debounceAutoCategoryCount(state) { | |
document.getElementById('category-count').disabled = state; | |
} | |