<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tableau HTML</title> <!-- Ajoutez le lien vers Bootstrap --> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"> <style> .table-container { width: 100%; overflow-x: auto; margin-bottom: 10px; } .fixed-column { position: sticky; left: 0; background: white; z-index: 2; border-left: 2px solid black; border-right: 1px solid black; padding-left: 10px; padding-right: 10px; width: 222px; min-width: 222px; } .second-fixed-column { position: sticky; left: 222px; background: white; z-index: 2; border-right: 1px solid black; padding-left: 5px; padding-right: 5px; width: 1px; min-width: 1px; white-space: nowrap; } th.fixed-column, th.second-fixed-column { top: 0; z-index: 3; } td:first-child { border-left: 2px solid black; } .active-cell { background-color: green; color: white; } .total-column { background-color: #f0f0f0; pointer-events: none; width: 25px; } .week-even { background-color: #e0f7fa; } .week-odd { background-color: #ffecb3; } .button-container { text-align: center; margin-top: 10px; } .grayed-out { background-color: #d3d3d3; pointer-events: none; } </style> </head> <body> <div class="table-container"> <table id="data-table" class="table table-bordered table-striped table-hover"> <thead> <tr> <th class="fixed-column">Nom</th> <th class="second-fixed-column total-column">Total</th> <?php $start_date = new DateTime("2025-01-01"); $end_date = new DateTime("2025-12-31"); $holidays = [ "01/01", "01/05", "08/05", "14/07", "15/08", "01/11", "11/11", "25/12", date("d/m", strtotime("2025-05-29")), date("d/m", strtotime("2025-06-08")) ]; $dates = []; while ($start_date <= $end_date) { $dayOfWeek = $start_date->format("N"); $formattedDate = $start_date->format("d"); if ($dayOfWeek < 6 && !in_array($formattedDate, $holidays)) { $weekNumber = $start_date->format("W"); $month = $start_date->format("m"); $dates[] = ["date" => $formattedDate, "week" => $weekNumber, "month" => $month]; } $start_date->modify("+1 day"); } $currentWeek = null; $weekClass = "week-even"; $lastMonth = null; $months = [ "01" => "Janvier", "02" => "Février", "03" => "Mars", "04" => "Avril", "05" => "Mai", "06" => "Juin", "07" => "Juillet", "08" => "Août", "09" => "Septembre", "10" => "Octobre", "11" => "Novembre", "12" => "Décembre" ]; foreach ($dates as $data) { $monthName = isset($months[$data['month']]) ? $months[$data['month']] : 'Mois inconnu'; if ($currentWeek !== $data['week']) { $currentWeek = $data['week']; $weekClass = ($weekClass === "week-even") ? "week-odd" : "week-even"; } echo "<th class='$weekClass'>{$data['date']}</th>"; } ?> </tr> </thead> <tbody> <tr> <td class="fixed-column">Mois</td> <td class="second-fixed-column"></td> <?php $currentMonth = null; $count = 1; foreach ($dates as $index => $data) { if ($currentMonth !== $data['month']) { if ($currentMonth !== null) { echo "<td colspan='$count'>{$months[$currentMonth]}</td>"; } $currentMonth = $data['month']; $count = 1; } else { $count++; } if ($index == count($dates) - 1) { echo "<td colspan='$count'>{$months[$currentMonth]}</td>"; } } ?> </tr> <tr> <td class="fixed-column">Semaine</td> <td class="second-fixed-column"></td> <?php $currentWeek = null; $weekCount = 1; foreach ($dates as $index => $data) { if ($currentWeek !== $data['week']) { if ($currentWeek !== null) { echo "<td colspan='$weekCount'>{$currentWeek}</td>"; } $currentWeek = $data['week']; $weekCount = 1; } else { $weekCount++; } if ($index == count($dates) - 1) { echo "<td colspan='$weekCount'>{$currentWeek}</td>"; } } ?> </tr> </tbody> </table> </div> <div class="button-container"> <button class="btn btn-primary" onclick="addRow()">Ajouter une ligne</button> <button class="btn btn-success" onclick="saveData()">SAUVER</button> <button class="btn btn-info" onclick="loadData()">CHARGER</button> </div> <script> //combien data-table contient de lignes. //il faut prendre les lignes dont l'indice est supérieur à 2 //on va venir recupérer pour chacunes de ces lignes le contenu des différentes cellules. function addRow() { let table = document.getElementById("data-table"); let row = table.insertRow(-1); // Première cellule - Combo Box let cell1 = row.insertCell(0); cell1.classList.add("fixed-column"); let select = document.createElement("select"); select.addEventListener("change", function(event) { // Ajouter ici des actions à effectuer lors de la sélection d'un item select.blur(); }); // Ajouter des options à la combo box let option1 = document.createElement("option"); option1.value = "Option 1"; option1.textContent = "Option 1"; select.appendChild(option1); let option2 = document.createElement("option"); option2.value = "Option 2"; option2.textContent = "Option 2"; select.appendChild(option2); let option3 = document.createElement("option"); option3.value = "Option 3"; option3.textContent = "Option 3"; select.appendChild(option3); // Ajouter le select dans la cellule cell1.appendChild(select); // Deuxième cellule - Total let cell2 = row.insertCell(1); cell2.classList.add("second-fixed-column", "total-column"); cell2.innerText = "0"; // Ajouter les autres cellules de la ligne for (let i = 2; i < table.rows[0].cells.length; i++) { let cell = row.insertCell(i); cell.innerText = "0"; cell.onclick = function() { toggleCell(cell, row); }; } } function toggleCell(cell, row) { if (cell.innerText === '0') { cell.innerText = '1'; cell.classList.add('active-cell'); } else { cell.innerText = '0'; cell.classList.remove('active-cell'); } updateTotal(row); } function updateTotal(row) { let total = 0; for (let i = 2; i < row.cells.length; i++) { let cellValue = parseInt(row.cells[i].innerText); if (!isNaN(cellValue)) { total += cellValue; } } row.cells[1].innerText = total; } /*function saveData() { alert("Les données ont été sauvegardées !"); // Logique de sauvegarde des données ici (par exemple, envoyer les données à un serveur ou les enregistrer localement) }*/ /* function saveData() { let table = document.getElementById("data-table"); let rows = table.rows; // Vérifier s'il y a plus de 2 lignes if (rows.length <= 2) { alert("Sauvegarde impossible : il n'y a pas suffisamment de données."); return; } let allData = []; // Tableau pour stocker les sous-tableaux JSON // Boucler à travers les lignes à partir de la 3ème ligne (index 2) for (let i = 2; i < rows.length; i++) { let row = rows[i]; let rowData = []; // Tableau pour stocker les données de chaque ligne // Récupérer les données de chaque cellule de la ligne for (let j = 0; j < row.cells.length; j++) { let cell = row.cells[j]; // Si la cellule est la première ou la seconde colonne, ajouter l'input ou le total if (j === 0) { // Ajout de la valeur de l'input si présent (pour la première colonne "Nom") let input = cell.querySelector('select') ? cell.querySelector('select').value : null; rowData.push(input || ""); // Ajoute l'input ou une chaîne vide si absent } else if (j === 1) { // Ajouter le total rowData.push(cell.innerText); // Valeur totale de la cellule } else { // Ajouter 0 ou 1 en fonction de l'état de la cellule rowData.push(cell.innerText === '1' ? 1 : 0); } } // Ajouter les données de la ligne au tableau principal allData.push(rowData); } // Convertir le tableau allData en JSON let jsonData = JSON.stringify(allData, null, 4); // Beautifier l'indentation pour rendre la sortie lisible alert(jsonData); console.log("Données sauvegardées :", jsonData); // Pour simuler une sauvegarde, tu peux l'envoyer à un serveur ou l'enregistrer localement. // Par exemple, afficher dans la console ou sauvegarder dans un fichier. alert("Données sauvegardées avec succès !"); } */ function saveDataaaa() { let table = document.getElementById("data-table"); let rows = table.rows; // Vérifier s'il y a plus de 2 lignes if (rows.length <= 2) { alert("Sauvegarde impossible : il n'y a pas suffisamment de données."); return; } let allData = []; // Tableau pour stocker les sous-tableaux JSON // Boucler à travers les lignes à partir de la 3ème ligne (index 2) for (let i = 2; i < rows.length; i++) { let row = rows[i]; let rowData = []; // Tableau pour stocker les données de chaque ligne // Récupérer les données de chaque cellule de la ligne for (let j = 0; j < row.cells.length; j++) { let cell = row.cells[j]; // Si la cellule est la première colonne (Nom), récupérer la valeur de l'input (select) if (j === 0) { let input = cell.querySelector('select') ? cell.querySelector('select').value : ""; console.log(" +++ " + input); rowData.push(input); // Ajoute la valeur de l'input ou une chaîne vide si absent } // Si la cellule est la deuxième colonne (Total), ajouter la valeur du total else if (j === 1) { rowData.push(cell.innerText.trim()); // Ajoute la valeur du total, retirer les espaces inutiles console.log(" +++ " + cell.innerText.trim()); } // Sinon, ajouter 0 ou 1 en fonction de l'état de la cellule else { rowData.push(cell.innerText.trim() === '1' ? 1 : 0); // Ajouter 0 ou 1 } } // Ajouter les données de la ligne au tableau principal allData.push(rowData); } // Convertir le tableau allData en JSON let jsonData = JSON.stringify(allData, null, 4); // Beautifier l'indentation pour rendre la sortie lisible alert(jsonData); console.log("Données sauvegardées :", jsonData); } function saveDatazzzz() { let table = document.getElementById("data-table"); let rows = table.rows; if (rows.length <= 2) { alert("Sauvegarde impossible : il n'y a pas suffisamment de données."); return; } let allData = []; for (let i = 2; i < rows.length; i++) { // Commence à partir de la troisième ligne let row = rows[i]; let rowData = []; let firstCell = row.cells[0]; // Première cellule de la ligne let input = firstCell.querySelector('select') ? firstCell.querySelector('select').value : ""; if (input === "") continue; // Ignore les lignes vides (sans valeur dans la première cellule) rowData.push(input); for (let j = 1; j < row.cells.length; j++) { let cell = row.cells[j]; let cellValue = cell.innerText.trim(); rowData.push(j === 1 ? cellValue : (cellValue === '1' ? 1 : 0)); } allData.push(rowData); } let jsonData = JSON.stringify(allData, null, 4); console.log("Données sauvegardées :", jsonData); alert(jsonData); } /* function saveData() { let table = document.getElementById("data-table"); let rows = table.rows; if (rows.length <= 2) { alert("Sauvegarde impossible : il n'y a pas suffisamment de données."); return; } let allData = []; for (let i = 2; i < rows.length; i++) { // Commence à la 3ème ligne (évite les entêtes) let row = rows[i]; let rowData = []; let firstCell = row.cells[0]; let input = firstCell.querySelector('select') ? firstCell.querySelector('select').value : ""; if (input === "") continue; // Ignore les lignes vides rowData.push(input); for (let j = 1; j < row.cells.length; j++) { let cell = row.cells[j]; let cellValue = cell.innerText.trim(); rowData.push(j === 1 ? cellValue : (cellValue === '1' ? 1 : 0)); } allData.push(rowData); } let jsonData = JSON.stringify(allData); // Envoi des données en AJAX avec XMLHttpRequest let xhr = new XMLHttpRequest(); xhr.open("POST", "saveData.php", true); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if (xhr.status == 200) { alert("Données enregistrées avec succès !"); console.log("Réponse du serveur :", xhr.responseText); } else { alert("Erreur lors de l'enregistrement."); } } }; xhr.send(jsonData); // Envoi du JSON } */ function saveData() { const rows = document.querySelectorAll('#data-table tr'); // Récupérer toutes les lignes du tableau let allData = []; // Ignorer les 2 premières lignes (en-têtes du tableau) for (let i = 3; i < rows.length; i++) { let row = rows[i]; let rowData = []; // Sélectionner la première cellule (Nom) let firstCell = row.cells[0]; let input = firstCell.querySelector('select') ? firstCell.querySelector('select').value : ""; rowData.push(input); // Récupérer les autres cellules for (let j = 1; j < row.cells.length; j++) { let cell = row.cells[j]; let cellValue = cell.innerText.trim(); rowData.push(j === 1 ? cellValue : (cellValue === '1' ? 1 : 0)); } allData.push(rowData); } let jsonData = JSON.stringify(allData, null, 4); console.log("Données sauvegardées :", jsonData); // Envoi des données à PHP via POST fetch('save_data01.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: jsonData }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Erreur lors de l\'envoi des données :', error)); /* // Envoi des données au script PHP via Fetch API fetch("save_data01.php", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ data: [["val1", "val2", "val3"], ["val4", "val5", "val6"]] }) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error("Erreur:", error)); */ } function saveData_initial() { let table = document.getElementById("data-table"); let rows = table.rows; if (rows.length <= 2) { alert("Sauvegarde impossible : il n'y a pas suffisamment de données."); return; } let allData = []; for (let i = 2; i < rows.length; i++) { // Commence à la 3ème ligne (évite les entêtes) let row = rows[i]; let rowData = []; let firstCell = row.cells[0]; let input = firstCell.querySelector('select') ? firstCell.querySelector('select').value : ""; if (input === "") continue; // Ignore les lignes vides rowData.push(input); for (let j = 1; j < row.cells.length; j++) { let cell = row.cells[j]; let cellValue = cell.innerText.trim(); rowData.push(j === 1 ? cellValue : (cellValue === '1' ? 1 : 0)); } allData.push(rowData); } let jsonData = JSON.stringify(allData); // Envoi des données en AJAX avec XMLHttpRequest let xhr = new XMLHttpRequest(); xhr.open("POST", "saveData.php", true); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if (xhr.status == 200) { alert("Données enregistrées avec succès !"); console.log("Réponse du serveur :", xhr.responseText); } else { alert("Erreur lors de l'enregistrement."); } } }; xhr.send(jsonData); // Envoi du JSON } /****************************************/ function loadData() { let xhr = new XMLHttpRequest(); xhr.open("GET", "recuperation.php", true); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { let response = JSON.parse(xhr.responseText); if (response.success) { alert("Youpi"); populateTable(response.data); } else { alert("Aucune donnée trouvée."); } } }; xhr.send(); } /****************************************/ function populateTable(data) { let table = document.getElementById("data-table"); // Supprimer les anciennes lignes (sauf l'en-tête et les premières lignes fixes) while (table.rows.length > 2) { table.deleteRow(2); } data.forEach(rowData => { let row = table.insertRow(-1); // Première colonne : Select let cell1 = row.insertCell(0); cell1.classList.add("fixed-column"); let select = document.createElement("select"); ["Option 1", "Option 2", "Option 3"].forEach(optionValue => { let option = document.createElement("option"); option.value = optionValue; option.textContent = optionValue; if (optionValue === rowData[0]) option.selected = true; select.appendChild(option); }); cell1.appendChild(select); // Deuxième colonne : Total let cell2 = row.insertCell(1); cell2.classList.add("second-fixed-column", "total-column"); cell2.innerText = rowData[1]; // Autres cellules for (let i = 2; i < rowData.length; i++) { let cell = row.insertCell(i); cell.innerText = rowData[i] === 1 ? '1' : '0'; if (rowData[i] === 1) cell.classList.add('active-cell'); cell.onclick = function () { toggleCell(cell, row); }; } }); } </script> <!-- Lien vers Bootstrap JS et dépendances --> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.0.6/dist/umd/popper.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> </body> </html>