<?php /* Actuellement, chacunes des lignes, quelques soit sont type (standard, estimation , speciale) peuvent être déplacées verticalement dans le tableau lors d'un drag and dropde façon indivuduel. Je veux changer ce comportement. Désormais, lorsque l'on souhaite déplacé une ligne standard ou une ligne estimation, il faut analyser tous les objets liaisons pour trouver celui que contient sooit l'id de la ligne standard ou bien l'id de la ligne estimation. Dés que ce dernier est identifier, on connait les identifiant qui seront déplacés. on sait que si on a selectionner avec la souris une ligne standard alors la ligne estimation se trouve en juste en dessous. par contre, si on a selectionner une ligne estimation, on sait que la ligne standard se trouve juste au dessus L'objectif est de déplacer simultanément la ligne standard ainsi que la ligne estimation pour réaliser le drag and drop. si on souhaite faire un drag and drop d'une ligne spéciale, il est impossible qu'une ligne spéciale puisse se situé entre un ligne standard et une ligne estimation qui font partie de la meme liaison je veux que si on clique sur le bouton droit de la souris à l'intérieur de la première cellule d'une ligne standard, il faut que le menu contextuel contienne l'option "Up Insert special". De meme, si on clique sur le bouton droit de la souris à l'intérieur de la premiére cellule d'une ligne estimation, le menu contextuel doit contenir l'option " down insert special". cela signifie que le menu contextuel qui est commun doit inclure un moyen qui va distinguer les deux types de lignes pour afficher le choix correspondant à la ligne. */ function getWorkingDays($startDate, $endDate, $holidays = []) { $start = strtotime($startDate); $end = strtotime($endDate); $workingDays = []; setlocale(LC_TIME, 'fr_FR.UTF-8'); for ($currentDate = $start; $currentDate <= $end; $currentDate = strtotime("+1 day", $currentDate)) { $dayOfWeek = date("N", $currentDate); if ($dayOfWeek < 6 && !in_array(date("Y-m-d", $currentDate), $holidays)) { $workingDays[] = [ 'day' => date("d", $currentDate), 'day_of_week_initial' => strtoupper(strftime("%A", $currentDate)[0]), 'week_number' => date("W", $currentDate), 'full_date' => date("Y-m-d", $currentDate) // Ajout de la date complète ]; } } return $workingDays; } function getFrenchHolidays($year) { $easterDate = easter_date($year); $holidays = []; // Jours fériés fixes $holidays[] = "$year-01-01"; // Jour de l'An $holidays[] = "$year-05-01"; // Fête du Travail $holidays[] = "$year-05-08"; // Victoire 1945 $holidays[] = "$year-07-14"; // Fête Nationale $holidays[] = "$year-08-15"; // Assomption $holidays[] = "$year-11-01"; // Toussaint $holidays[] = "$year-11-11"; // Armistice $holidays[] = "$year-12-25"; // Noël // Jours fériés variables (calculés à partir de Pâques) $easter = new DateTime("@$easterDate"); $easter->setTimezone(new DateTimeZone(date_default_timezone_get())); $holidays[] = $easter->format("Y-m-d"); // Pâques (non férié officiellement mais utile) $holidays[] = $easter->modify('+1 day')->format("Y-m-d"); // Lundi de Pâques $holidays[] = $easter->modify('+38 days')->format("Y-m-d"); // Ascension $holidays[] = $easter->modify('+11 days')->format("Y-m-d"); // Lundi de Pentecôte return $holidays; } $year = 2025; $holidays = []; $holidays = getFrenchHolidays($year); // Liste des jours fériés et fêtes religieuses à exclure (exemple pour la France, à compléter avec d'autres fêtes) $old_holidays = [ "2025-01-01", // Jour de l'An "2025-04-14", // Lundi de Pâques "2025-05-01", // Fête du Travail "2025-05-08", // Victoire 1945 "2025-07-14", // Bastille "2025-08-15", // Assomption "2025-11-01", // Toussaint "2025-12-25", // Noël "2026-01-01", // Jour de l'An "2026-04-06", // Lundi de Pâques // Ajouter d'autres jours fériés ici... ]; // Définir la période de début et de fin $startDate = "2025-01-10"; $endDate = "2026-02-14"; // Appeler la fonction pour obtenir les jours ouvrés entre les deux dates $workingDays = getWorkingDays($startDate, $endDate, $holidays); ?> <!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tableau Sticky - 3 Lignes Fixes</title> <style> .table-wrapper { width: 100%; height: calc(100vh - 100px); overflow: auto; border: 1px solid #ccc; position: relative; } table { border-collapse: collapse; width: max-content; table-layout: fixed; } th, td { padding: 3px; text-align: center; height: 40px; border: 1px solid #ccc; white-space: nowrap; min-width: 120px; position: relative; background-color: white; box-sizing: border-box; } th { background-color: #f2f2f2; position: sticky; top: 0; z-index: 100; } th:first-child, td:first-child { position: sticky; left: 0; z-index: 101; background-color: white; } th:nth-child(2), td:nth-child(2) { position: sticky; left: 120px; z-index: 100; background-color: white; } th:nth-child(3), td:nth-child(3) { position: sticky; left: 240px; z-index: 99; background-color: white; } th:first-child::after, td:first-child::after, th:nth-child(2)::after, td:nth-child(2)::after, th:nth-child(3)::after, td:nth-child(3)::after { content: ""; position: absolute; right: 0; top: 0; width: 2px; height: 100%; background-color: #ccc; z-index: 102; } tbody tr:nth-child(odd) { background-color: #f9f9f9; } th:nth-child(n+4), td:nth-child(n+4) { min-width: 40px; max-width: 40px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .second-header th { background-color: #f2f2f2; position: sticky; top: 40px; z-index: 99; } .third-header th { background-color: #f2f2f2; position: sticky; top: 80px; z-index: 98; } .second-header th:first-child, .third-header th:first-child { left: 0; z-index: 101; background-color: white; } .second-header th:nth-child(2), .third-header th:nth-child(2) { left: 120px; z-index: 100; background-color: white; } .second-header th:nth-child(3), .third-header th:nth-child(3) { left: 240px; z-index: 99; background-color: white; } thead tr:first-child th:first-child, thead tr:first-child th:nth-child(2), thead tr:first-child th:nth-child(3) { z-index: 105; background-color: #ddd; } .second-header th:first-child, .second-header th:nth-child(2), .second-header th:nth-child(3) { z-index: 104; } .third-header th:first-child, .third-header th:nth-child(2), .third-header th:nth-child(3) { z-index: 103; } thead tr:first-child th, .second-header th, .third-header th { box-shadow: inset 0 -2px #aaa; background-clip: padding-box; padding-bottom: 2px; margin-bottom: -2px; z-index: 100; } .second-header th { top: calc(40px + 2px); margin-top: 2px; } .third-header th { top: calc(80px + 2px); margin-top: 2px; } .even-week { background-color: #ffcc99 !important; } .odd-week { background-color: #e6b3ff !important; } .fourth-header th { background-color: #f2f2f2; position: sticky; top: 120px; z-index: 97; } .fourth-header th:first-child { left: 0; z-index: 101; background-color: white; } .fourth-header th:nth-child(2) { left: 120px; z-index: 100; background-color: white; } .fourth-header th:nth-child(3) { left: 240px; z-index: 99; background-color: white; } .fourth-header th:first-child, .fourth-header th:nth-child(2), .fourth-header th:nth-child(3) { z-index: 102; } .fourth-header th { top: calc(120px + 2px); margin-top: 2px; } .fourth-header th { box-shadow: inset 0 -2px #aaa; background-clip: padding-box; padding-bottom: 2px; margin-bottom: -2px; z-index: 97; } .month-even { background-color: #99ccff !important; } .month-odd { background-color: #ff9999 !important; } .btn { margin-bottom: 20px; padding: 10px; background-color: #4CAF50; color: white; border: none; cursor: pointer; font-size: 16px; border-radius: 5px; transition: background-color 0.3s ease; } .btn:hover { background-color: #45a049; } .btn-special { background-color: #2196F3; } .btn-special:hover { background-color: #1e88e5; } .btn-special:hover { background-color: #1e88e5; } #contextMenu { position: absolute; display: none; flex-direction: column; background: white; border: 1px solid #ccc; box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); border-radius: 5px; z-index: 1000; min-width: 180px; } #contextMenu .dropdown-item { display: block; width: 100%; padding: 8px 12px; text-align: left; color: #333; cursor: pointer; } #contextMenu .dropdown-item:hover { background: #f8f9fa; } #specialContextMenu { position: absolute; display: none; flex-direction: column; background: white; border: 1px solid #ccc; box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); border-radius: 5px; z-index: 1000; min-width: 180px; } #specialContextMenu .dropdown-item { display: block; width: 100%; padding: 8px 12px; text-align: left; color: #333; cursor: pointer; } #specialContextMenu .dropdown-item:hover { background: #f8f9fa; } #colorContextMenu { position: absolute; display: none; flex-direction: column; background: white; border: 1px solid #ccc; box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); border-radius: 5px; z-index: 1000; min-width: 180px; } #colorContextMenu .dropdown-item { display: block; width: 100%; padding: 8px 12px; text-align: left; color: #333; cursor: pointer; } #colorContextMenu .dropdown-item:hover { background: #f8f9fa; } .add-button { background-color: orange; color: white; border: none; padding: 5px 10px; cursor: pointer; margin-left: 5px; } .editable-input { width: 65px; box-sizing: border-box; } .collapsed { display: none; } #jsonOutput { margin-top: 20px; padding: 10px; border: 1px solid #ccc; background-color: #f9f9f9; white-space: pre-wrap; word-wrap: break-word; } #logOutput { margin-top: 20px; padding: 10px; border: 1px solid #ccc; background-color: #f9f9f9; white-space: pre-wrap; word-wrap: break-word; } .no-click { pointer-events: none; } #debugOutput { margin-top: 20px; padding: 10px; border: 1px solid #ccc; background-color: #f9f9f9; white-space: pre-wrap; word-wrap: break-word; } </style> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> </head> <body> <div class="modal fade" id="confirmationModal" tabindex="-1" aria-labelledby="confirmationModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="confirmationModalLabel">Confirmation</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span> </button> </div> <div class="modal-body"> Voulez-vous vraiment supprimer cette ligne ? </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" id="cancelDelete">Annuler</button> <button type="button" class="btn btn-danger" id="confirmDelete">OK</button> </div> </div> </div> </div> <div class="modal fade" id="successModal" tabindex="-1" aria-labelledby="successModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="successModalLabel">Succès</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span> </button> </div> <div class="modal-body"> Données sauvegardées avec succès ! </div> <div class="modal-footer"> <button type="button" class="btn btn-primary" id="closeSuccessModal">OK</button> </div> </div> </div> </div> <div class="modal fade" id="messageModal" tabindex="-1" aria-labelledby="messageModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="messageModalLabel">Message</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span> </button> </div> <div class="modal-body" id="messageModalBody"> </div> <div class="modal-footer"> <button type="button" class="btn btn-primary" data-dismiss="modal">OK</button> </div> </div> </div> </div> <div id="colorContextMenu" class="dropdown-menu" style="display: none;"> <button class="dropdown-item" style="background-color: green;" data-color="green">Vert</button> <button class="dropdown-item" style="background-color: blue;" data-color="blue">Bleu</button> <button class="dropdown-item" style="background-color: red;" data-color="red">Rouge</button> <button class="dropdown-item" style="background-color: yellow;" data-color="yellow">Jaune</button> <button class="dropdown-item" style="background-color: orange;" data-color="orange">Orange</button> <button class="dropdown-item" style="background-color: purple;" data-color="purple">Violet</button> <button class="dropdown-item" style="background-color: pink;" data-color="pink">Rose</button> <button class="dropdown-item" style="background-color: brown;" data-color="brown">Marron</button> <button class="dropdown-item" style="background-color: cyan;" data-color="cyan">Cyan</button> <button class="dropdown-item" style="background-color: gray;" data-color="gray">Gris</button> </div> <div class="modal fade" id="rangeSelectionModal" tabindex="-1" aria-labelledby="rangeSelectionModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="rangeSelectionModalLabel">Sélection de Plage</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span> </button> </div> <div class="modal-body"> <div class="form-group"> <label for="startCellId">Cellule de Départ</label> <input type="text" class="form-control" id="startCellId" disabled> </div> <div class="form-group"> <label for="endCellId">Cellule de Fin</label> <input type="text" class="form-control" id="endCellId"> </div> <div class="form-group"> <label for="rangeComboBox">Sélectionnez une valeur</label> <select class="form-control" id="rangeComboBox"> </select> </div> <div id="rangeResult" class="form-group"> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" id="cancelRangeSelection">Annuler</button> <button type="button" class="btn btn-primary" id="confirmRangeSelection">Valider</button> </div> </div> </div> </div> <div class="table-wrapper"> <table> <thead> <tr> <th></th> <th>plouf</th> <th>cretin</th> <?php foreach ($workingDays as $dateData): ?> <th> <?php echo $dateData['day']; ?> <br> </th> <?php endforeach; ?> </tr> <tr class="second-header"> <th></th> <th>Valeur 1</th> <th>Valeur 2</th> <?php $currentWeek = null; $weekClass = ""; foreach ($workingDays as $dateData): if ($currentWeek !== $dateData['week_number']) { $currentWeek = $dateData['week_number']; $weekClass = ($currentWeek % 2 === 0) ? 'even-week' : 'odd-week'; } ?> <th class="<?= $weekClass; ?>"><?php echo $dateData['day_of_week_initial']; ?></th> <?php endforeach; ?> </tr> <tr class="third-header"> <th></th> <th>Info 1</th> <th>Info 2</th> <?php $currentWeek = null; $colspan = 0; foreach ($workingDays as $index => $dateData): if ($currentWeek !== $dateData['week_number']) { if ($currentWeek !== null) { $weekClass = $currentWeek % 2 === 0 ? 'even-week' : 'odd-week'; echo '<th class="' . $weekClass . '" colspan="' . $colspan . '">' . $currentWeek . '</th>'; } $currentWeek = $dateData['week_number']; $colspan = 1; } else { $colspan++; } endforeach; if ($currentWeek !== null) { $weekClass = $currentWeek % 2 === 0 ? 'even-week' : 'odd-week'; echo '<th class="' . $weekClass . '" colspan="' . $colspan . '">' . $currentWeek . '</th>'; } ?> </tr> <tr class="fourth-header"> <th></th> <th>Label 1</th> <th>Label 2</th> <?php $currentMonthYear = null; $colspan = 0; $monthClass = ""; $colorIndex = 0; $colors = ['month-even', 'month-odd']; foreach ($workingDays as $index => $dateData): $monthYear = ucfirst(strftime("%B %Y", strtotime($dateData['full_date']))); if ($currentMonthYear !== $monthYear) { if ($currentMonthYear !== null) { echo '<th class="' . $monthClass . '" colspan="' . $colspan . '">' . $currentMonthYear . '</th>'; } $currentMonthYear = $monthYear; $colspan = 1; $monthClass = $colors[$colorIndex % 2]; $colorIndex++; } else { $colspan++; } endforeach; if ($currentMonthYear !== null) { echo '<th class="' . $monthClass . '" colspan="' . $colspan . '">' . $currentMonthYear . '</th>'; } ?> </tr> </thead> <tbody> </tbody> </table> </div> <button id="addRowButton" class="btn">Ajouter une ligne</button> <button id="addSpecialRowButton" class="btn btn-special">Ajouter une ligne spéciale</button> <button id="logButton" class="btn">Log</button> <button id="buildButton" class="btn">Build</button> <button id="blablaButton" class="btn">Blabla</button> <button id="queryButton" class="btn">Query</button> <div id="generatedDataOutput"></div> <div id="jsonOutput"></div> <div id="debugOutput"></div> <script> document.addEventListener("DOMContentLoaded", function () { const tableBody = document.querySelector("tbody"); let specialRowCounter = 1; let rowCounter = 1; let linkageCounter = 1; let standardRowsData = []; let estimationRowsData = []; let specialRowsData = []; // Tableau dédié pour stocker les objets des lignes spéciales let linkages = []; const specialRowStates = {}; const associations = {}; let currentCell = null; let keydownHandled = false; let alertShown = false; let selectedRow = null; // Variable to keep track of the selected row const contextMenu = document.createElement("div"); contextMenu.id = "contextMenu"; contextMenu.classList.add("dropdown-menu"); contextMenu.style.display = "none"; document.body.appendChild(contextMenu); const specialContextMenu = document.createElement("div"); specialContextMenu.id = "specialContextMenu"; specialContextMenu.classList.add("dropdown-menu"); specialContextMenu.style.display = "none"; document.body.appendChild(specialContextMenu); const colorContextMenu = document.getElementById("colorContextMenu"); const colorButtons = colorContextMenu.querySelectorAll(".dropdown-item"); colorButtons.forEach(button => { button.addEventListener("click", function () { const color = this.getAttribute("data-color"); const cell = document.querySelector(".selected-cell"); if (cell) { cell.style.backgroundColor = color; cell.dataset.cellColor = color; hideColorContextMenu(); updateRowData(cell); } }); }); function generateRandomId(length = 8) { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * characters.length)); } return result; } function addRow(afterRow = null) { const rowNumber = tableBody.rows.length + 1; const newRow = document.createElement("tr"); newRow.setAttribute("draggable", "true"); newRow.dataset.rowId = `standard-${generateRandomId()}`; newRow.title = newRow.dataset.rowId; // Ajoutez cette ligne const rowData = { id: newRow.dataset.rowId, name: `Row ${rowNumber}`, selectValue: "1", count: "0", cells: [], selection: "OFF" // TAG : SELECTION }; const firstCells = [`Row ${rowNumber}`, "", "0"]; firstCells.forEach((text, index) => { const td = document.createElement("td"); td.dataset.cellId = `cell-${rowData.id}-${index}`; if (index === 0) { const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = rowData.name; input.addEventListener("click", function (event) { event.stopPropagation(); input.focus(); input.style.width = "130px"; }); input.addEventListener("blur", function () { if (!keydownHandled && !alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } keydownHandled = false; alertShown = false; }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { keydownHandled = true; if (!alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } } }); td.appendChild(input); } else if (index === 1) { const select = document.createElement("select"); for (let i = 1; i <= 10; i++) { const option = document.createElement("option"); option.value = i; option.textContent = `Option ${i}`; select.appendChild(option); } select.value = rowData.selectValue; select.addEventListener("change", function () { updateRowData(select); }); td.appendChild(select); } else { td.textContent = text; } if (index === 0) { td.classList.add("row-header"); td.addEventListener("click", function () { handleRowClick(newRow, td); // TAG : SELECTION }); td.addEventListener("contextmenu", function (event) { event.preventDefault(); showContextMenu(event, newRow); }); } newRow.appendChild(td); }); const headerCells = document.querySelectorAll("thead tr:nth-child(2) th:not(.weekend):not(.holiday)"); const workingDaysCount = headerCells.length; for (let i = 0; i < workingDaysCount - 3; i++) { const td = document.createElement("td"); td.dataset.cellId = `cell-${rowData.id}-${i}`; td.dataset.cellValue = "0"; td.dataset.cellColor = "white"; td.textContent = "0"; td.style.backgroundColor = "white"; td.addEventListener("click", function () { const newValue = td.dataset.cellValue === "0" ? "1" : "0"; td.dataset.cellValue = newValue; td.textContent = newValue; td.style.backgroundColor = newValue === "1" ? "green" : "white"; td.dataset.cellColor = newValue === "1" ? "green" : "white"; updateCountCell(newRow); updateRowData(td); }); td.addEventListener("contextmenu", function (event) { event.preventDefault(); if (td.dataset.cellValue === "1") { showColorContextMenu(event, td); } }); td.title = `ID: ${td.dataset.cellId}`; newRow.appendChild(td); rowData.cells.push({ value: "0", color: "white" }); } if (afterRow) { tableBody.insertBefore(newRow, afterRow.nextSibling); } else { tableBody.appendChild(newRow); } newRow.addEventListener("dragstart", dragStart); newRow.addEventListener("dragover", dragOver); newRow.addEventListener("drop", drop); rowCounter++; standardRowsData.push(rowData); const estimationRow = document.createElement("tr"); estimationRow.setAttribute("draggable", "true"); estimationRow.dataset.rowId = `estimation-${generateRandomId()}`; estimationRow.classList.add("estimation-row"); estimationRow.title = estimationRow.dataset.rowId; // Ajoutez cette ligne const estimationRowData = { id: estimationRow.dataset.rowId, name: `Estimation ${rowNumber}`, selectValue: "1", estimationValue: "0", selection: "OFF" // TAG : SELECTION }; const estimationFirstCells = [`Estimation ${rowNumber}`, "", "0"]; estimationFirstCells.forEach((text, index) => { const td = document.createElement("td"); td.dataset.cellId = `cell-${estimationRowData.id}-${index}`; if (index === 0) { const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = estimationRowData.name; input.addEventListener("click", function (event) { event.stopPropagation(); input.focus(); input.style.width = "130px"; }); input.addEventListener("blur", function () { if (!keydownHandled && !alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } keydownHandled = false; alertShown = false; }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { keydownHandled = true; if (!alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } } }); td.appendChild(input); } else if (index === 1) { const select = document.createElement("select"); for (let i = 1; i <= 10; i++) { const option = document.createElement("option"); option.value = i; option.textContent = `Option ${i}`; select.appendChild(option); } select.value = estimationRowData.selectValue; select.addEventListener("change", function () { updateRowData(select); }); td.appendChild(select); } else { const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = "1"; input.addEventListener("click", function (event) { event.stopPropagation(); input.focus(); input.style.width = "130px"; }); input.addEventListener("blur", function () { if (!keydownHandled && !alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; const value = parseInt(input.value, 10); if (isNaN(value) || value < 1 || value > 365) { input.value = "1"; showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365."); } else { updateRowData(input); } } keydownHandled = false; alertShown = false; }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { keydownHandled = true; if (!alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; const value = parseInt(input.value, 10); if (isNaN(value) || value < 1 || value > 365) { input.value = "1"; showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365."); } else { updateRowData(input); } } } }); td.appendChild(input); } if (index === 0) { td.classList.add("row-header"); td.addEventListener("click", function () { handleRowClick(estimationRow, td); // TAG : SELECTION }); td.addEventListener("contextmenu", function (event) { event.preventDefault(); showContextMenu(event, estimationRow); }); } estimationRow.appendChild(td); }); const mergedCell = document.createElement("td"); mergedCell.colSpan = workingDaysCount - 3; mergedCell.textContent = ""; mergedCell.classList.add("no-click"); estimationRow.appendChild(mergedCell); if (afterRow) { tableBody.insertBefore(estimationRow, newRow.nextSibling); } else { tableBody.appendChild(estimationRow); } estimationRow.addEventListener("dragstart", dragStart); estimationRow.addEventListener("dragover", dragOver); estimationRow.addEventListener("drop", drop); const linkage = { id: `linkage-${generateRandomId()}`, // Remplacez linkageId par id standardRowId: newRow.dataset.rowId, estimationRowId: estimationRow.dataset.rowId }; linkages.push(linkage); displayLinkages(); rowCounter++; estimationRowsData.push(estimationRowData); } /* function handleRowClick(row, td) { // TAG : SELECTION const rowId = row.dataset.rowId; let linkedRowId = null; let linkedRow = null; if (rowId.startsWith("standard-")) { const linkage = linkages.find(link => link.standardRowId === rowId); if (linkage) { linkedRowId = linkage.estimationRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } else if (rowId.startsWith("estimation-")) { const linkage = linkages.find(link => link.estimationRowId === rowId); if (linkage) { linkedRowId = linkage.standardRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } if (linkedRow) { if (selectedRow && selectedRow !== row) { showMessageModal("Vous ne pouvez sélectionner qu'une seule ligne à la fois."); return; } const standardRowData = standardRowsData.find(data => data.id === rowId) || standardRowsData.find(data => data.id === linkedRowId); const estimationRowData = estimationRowsData.find(data => data.id === rowId) || estimationRowsData.find(data => data.id === linkedRowId); if (standardRowData.selection === "OFF" && estimationRowData.selection === "OFF") { console.log(`ID de la ligne standard : ${standardRowData.id}`); console.log(`ID de la ligne d'estimation : ${estimationRowData.id}`); standardRowData.selection = "ON"; estimationRowData.selection = "ON"; td.style.backgroundColor = "red"; linkedRow.cells[0].style.backgroundColor = "red"; selectedRow = row; // Update the selected row } else if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") { standardRowData.selection = "OFF"; estimationRowData.selection = "OFF"; td.style.backgroundColor = "white"; linkedRow.cells[0].style.backgroundColor = "white"; selectedRow = null; // Reset the selected row } } } */ /* function handleRowClick(row, td) { // TAG : SELECTION const rowId = row.dataset.rowId; let linkedRowId = null; let linkedRow = null; if (rowId.startsWith("standard-")) { const linkage = linkages.find(link => link.standardRowId === rowId); if (linkage) { linkedRowId = linkage.estimationRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } else if (rowId.startsWith("estimation-")) { const linkage = linkages.find(link => link.estimationRowId === rowId); if (linkage) { linkedRowId = linkage.standardRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } if (linkedRow) { if (selectedRow && selectedRow !== row) { showMessageModal("Vous ne pouvez sélectionner qu'une seule ligne à la fois."); return; } const standardRowData = standardRowsData.find(data => data.id === rowId) || standardRowsData.find(data => data.id === linkedRowId); const estimationRowData = estimationRowsData.find(data => data.id === rowId) || estimationRowsData.find(data => data.id === linkedRowId); if (standardRowData.selection === "OFF" && estimationRowData.selection === "OFF") { console.log(`ID de la ligne standard : ${standardRowData.id}`); console.log(`ID de la ligne d'estimation : ${estimationRowData.id}`); standardRowData.selection = "ON"; estimationRowData.selection = "ON"; td.style.backgroundColor = "red"; linkedRow.cells[0].style.backgroundColor = "red"; selectedRow = row; // Update the selected row } else if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") { standardRowData.selection = "OFF"; estimationRowData.selection = "OFF"; td.style.backgroundColor = "white"; linkedRow.cells[0].style.backgroundColor = "white"; selectedRow = null; // Reset the selected row } } } */ /* function handleRowClick(row, td) { // TAG : SELECTION const rowId = row.dataset.rowId; let linkedRowId = null; let linkedRow = null; if (rowId.startsWith("standard-")) { const linkage = linkages.find(link => link.standardRowId === rowId); if (linkage) { linkedRowId = linkage.estimationRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } else if (rowId.startsWith("estimation-")) { const linkage = linkages.find(link => link.estimationRowId === rowId); if (linkage) { linkedRowId = linkage.standardRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } if (linkedRow) { const standardRowData = standardRowsData.find(data => data.id === rowId) || standardRowsData.find(data => data.id === linkedRowId); const estimationRowData = estimationRowsData.find(data => data.id === rowId) || estimationRowsData.find(data => data.id === linkedRowId); if (standardRowData.selection === "OFF" && estimationRowData.selection === "OFF") { console.log(`ID de la ligne standard : ${standardRowData.id}`); console.log(`ID de la ligne d'estimation : ${estimationRowData.id}`); standardRowData.selection = "ON"; estimationRowData.selection = "ON"; td.style.backgroundColor = "red"; linkedRow.cells[0].style.backgroundColor = "red"; selectedRow = row; // Update the selected row } else if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") { standardRowData.selection = "OFF"; estimationRowData.selection = "OFF"; td.style.backgroundColor = "white"; linkedRow.cells[0].style.backgroundColor = "white"; selectedRow = null; // Reset the selected row } } } */ /* function handleRowClick(row, td) { // TAG : SELECTION const rowId = row.dataset.rowId; let linkedRowId = null; let linkedRow = null; if (rowId.startsWith("standard-")) { const linkage = linkages.find(link => link.standardRowId === rowId); if (linkage) { linkedRowId = linkage.estimationRowId; console.log("ORIGINE " + linkedRowId); linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } else if (rowId.startsWith("estimation-")) { const linkage = linkages.find(link => link.estimationRowId === rowId); if (linkage) { linkedRowId = linkage.standardRowId; console.log("ORIGINE " + linkedRowId); linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } if (linkedRow) { const standardRowData = standardRowsData.find(data => data.id === rowId) || standardRowsData.find(data => data.id === linkedRowId); const estimationRowData = estimationRowsData.find(data => data.id === rowId) || estimationRowsData.find(data => data.id === linkedRowId); // Vérifiez si les lignes sont déjà sélectionnées if (standardRowData.selection === "OFF" && estimationRowData.selection === "OFF") { // Si aucune ligne n'est sélectionnée, vérifiez si objet_selection contient déjà des identifiants if (Object.keys(objet_selection).length > 0) { showMessageModal("Vous ne pouvez sélectionner qu'un seule couple à la fois."); return; } // Mettez à jour l'état de sélection et mémorisez les identifiants standardRowData.selection = "ON"; estimationRowData.selection = "ON"; td.style.backgroundColor = "red"; linkedRow.cells[0].style.backgroundColor = "red"; // Mémorisez les identifiants dans objet_selection objet_selection.standardRowId = standardRowData.id; objet_selection.estimationRowId = estimationRowData.id; selectedRow = row; // Mettez à jour la ligne sélectionnée } else if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") { // Si les lignes sont déjà sélectionnées, désélectionnez-les standardRowData.selection = "OFF"; estimationRowData.selection = "OFF"; td.style.backgroundColor = "white"; linkedRow.cells[0].style.backgroundColor = "white"; // Supprimez les identifiants de objet_selection delete objet_selection.standardRowId; delete objet_selection.estimationRowId; selectedRow = null; // Réinitialisez la ligne sélectionnée } } else { // Si aucune ligne liée n'est trouvée, vérifiez si une sélection est déjà en cours if (Object.keys(objet_selection).length > 0) { showMessageModal("Vous ne pouvez sélectionner qu'un seul couple à la fois."); return; } } } */ /* function handleRowClick(row, td) { // TAG : SELECTION const rowId = row.dataset.rowId; selection_origine = rowId; // Mémorisez l'ID de la ligne cliquée let linkedRowId = null; let linkedRow = null; if (rowId.startsWith("standard-")) { const linkage = linkages.find(link => link.standardRowId === rowId); if (linkage) { linkedRowId = linkage.estimationRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } else if (rowId.startsWith("estimation-")) { const linkage = linkages.find(link => link.estimationRowId === rowId); if (linkage) { linkedRowId = linkage.standardRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } if (linkedRow) { const standardRowData = standardRowsData.find(data => data.id === rowId) || standardRowsData.find(data => data.id === linkedRowId); const estimationRowData = estimationRowsData.find(data => data.id === rowId) || estimationRowsData.find(data => data.id === linkedRowId); if (standardRowData.selection === "OFF" && estimationRowData.selection === "OFF") { console.log(`ID de la ligne standard : ${standardRowData.id}`); console.log(`ID de la ligne d'estimation : ${estimationRowData.id}`); standardRowData.selection = "ON"; estimationRowData.selection = "ON"; td.style.backgroundColor = "red"; linkedRow.cells[0].style.backgroundColor = "red"; // Mémorisez les identifiants dans objet_selection objet_selection.standardRowId = standardRowData.id; objet_selection.estimationRowId = estimationRowData.id; selectedRow = row; // Mettez à jour la ligne sélectionnée } else if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") { standardRowData.selection = "OFF"; estimationRowData.selection = "OFF"; td.style.backgroundColor = "white"; linkedRow.cells[0].style.backgroundColor = "white"; // Supprimez les identifiants de objet_selection delete objet_selection.standardRowId; delete objet_selection.estimationRowId; selectedRow = null; // Réinitialisez la ligne sélectionnée } } else { // Si aucune ligne liée n'est trouvée, vérifiez si une sélection est déjà en cours if (Object.keys(objet_selection).length > 0) { showMessageModal("Vous ne pouvez sélectionner qu'une seule ligne à la fois."); return; } } } */ // Déclarez la variable selection_origine en dehors de la fonction pour qu'elle soit accessible globalement ////let selection_origine = null; /* function handleRowClick(row, td) { // TAG : SELECTION const rowId = row.dataset.rowId; selection_origine = rowId; // Mémorisez l'ID de la ligne cliquée console.log("Valeur de selection_origine :", selection_origine); // Affichez la valeur de selection_origine dans la console let linkedRowId = null; let linkedRow = null; if (rowId.startsWith("standard-")) { const linkage = linkages.find(link => link.standardRowId === rowId); if (linkage) { linkedRowId = linkage.estimationRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } else if (rowId.startsWith("estimation-")) { const linkage = linkages.find(link => link.estimationRowId === rowId); if (linkage) { linkedRowId = linkage.standardRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } if (linkedRow) { const standardRowData = standardRowsData.find(data => data.id === rowId) || standardRowsData.find(data => data.id === linkedRowId); const estimationRowData = estimationRowsData.find(data => data.id === rowId) || estimationRowsData.find(data => data.id === linkedRowId); if (standardRowData.selection === "OFF" && estimationRowData.selection === "OFF") { console.log(`ID de la ligne standard : ${standardRowData.id}`); console.log(`ID de la ligne d'estimation : ${estimationRowData.id}`); standardRowData.selection = "ON"; estimationRowData.selection = "ON"; td.style.backgroundColor = "red"; linkedRow.cells[0].style.backgroundColor = "red"; // Mémorisez les identifiants dans objet_selection objet_selection.standardRowId = standardRowData.id; objet_selection.estimationRowId = estimationRowData.id; selectedRow = row; // Mettez à jour la ligne sélectionnée } else if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") { standardRowData.selection = "OFF"; estimationRowData.selection = "OFF"; td.style.backgroundColor = "white"; linkedRow.cells[0].style.backgroundColor = "white"; // Supprimez les identifiants de objet_selection delete objet_selection.standardRowId; delete objet_selection.estimationRowId; selectedRow = null; // Réinitialisez la ligne sélectionnée } } else { // Si aucune ligne liée n'est trouvée, vérifiez si une sélection est déjà en cours if (Object.keys(objet_selection).length > 0) { showMessageModal("Vous ne pouvez sélectionner qu'une seule ligne à la fois."); return; } } } */ // Déclarez l'objet objet_up en dehors de la fonction pour qu'il soit accessible globalement //const objet_up = {}; /*function handleRowClick(row, td) { // TAG : SELECTION console.log("++++++++"); const rowId = row.dataset.rowId; selection_origine = rowId; // Mémorisez l'ID de la ligne cliquée console.log("Valeur de selection_origine :", selection_origine); // Affichez la valeur de selection_origine dans la console // Réinitialisez l'objet objet_up objet_up.length = 0; // Collectez les IDs des lignes au-dessus de la ligne cliquée let currentRow = row.previousElementSibling; while (currentRow) { objet_up[currentRow.dataset.rowId] = true; currentRow = currentRow.previousElementSibling; } // Affichez les IDs stockés dans objet_up dans la console console.log("IDs des lignes au-dessus (objet_up) :", Object.keys(objet_up)); let linkedRowId = null; let linkedRow = null; if (rowId.startsWith("standard-")) { const linkage = linkages.find(link => link.standardRowId === rowId); if (linkage) { linkedRowId = linkage.estimationRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } else if (rowId.startsWith("estimation-")) { const linkage = linkages.find(link => link.estimationRowId === rowId); if (linkage) { linkedRowId = linkage.standardRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } if (linkedRow) { const standardRowData = standardRowsData.find(data => data.id === rowId) || standardRowsData.find(data => data.id === linkedRowId); const estimationRowData = estimationRowsData.find(data => data.id === rowId) || estimationRowsData.find(data => data.id === linkedRowId); if (standardRowData.selection === "OFF" && estimationRowData.selection === "OFF") { console.log(`ID de la ligne standard : ${standardRowData.id}`); console.log(`ID de la ligne d'estimation : ${estimationRowData.id}`); standardRowData.selection = "ON"; estimationRowData.selection = "ON"; td.style.backgroundColor = "red"; linkedRow.cells[0].style.backgroundColor = "red"; // Mémorisez les identifiants dans objet_selection objet_selection.standardRowId = standardRowData.id; objet_selection.estimationRowId = estimationRowData.id; selectedRow = row; // Mettez à jour la ligne sélectionnée } else if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") { standardRowData.selection = "OFF"; estimationRowData.selection = "OFF"; td.style.backgroundColor = "white"; linkedRow.cells[0].style.backgroundColor = "white"; // Supprimez les identifiants de objet_selection delete objet_selection.standardRowId; delete objet_selection.estimationRowId; selectedRow = null; // Réinitialisez la ligne sélectionnée } } else { // Si aucune ligne liée n'est trouvée, vérifiez si une sélection est déjà en cours if (Object.keys(objet_selection).length > 0) { showMessageModal("Vous ne pouvez sélectionner qu'une seule ligne à la fois."); return; } } } */ // Déclarez la variable selection_origine en dehors de la fonction pour qu'elle soit accessible globalement let selection_origine = null; // Déclarez l'objet objet_up en dehors de la fonction pour qu'il soit accessible globalement let objet_up = {}; // Déclarez l'objet objet_selection en dehors de la fonction pour qu'il soit accessible globalement const objet_selection = {}; function handleRowClick(row, td) { // TAG : SELECTION const rowId = row.dataset.rowId; selection_origine = rowId; // Mémorisez l'ID de la ligne cliquée console.log("Valeur de selection_origine :", selection_origine); // Affichez la valeur de selection_origine dans la console // Réinitialisez l'objet objet_up objet_up = {}; // Collectez les IDs des lignes au-dessus de la ligne cliquée let currentRow = row.previousElementSibling; while (currentRow) { objet_up[currentRow.dataset.rowId] = true; currentRow = currentRow.previousElementSibling; } // Affichez les IDs stockés dans objet_up dans la console console.log("IDs des lignes au-dessus (objet_up) :", Object.keys(objet_up)); let linkedRowId = null; let linkedRow = null; if (rowId.startsWith("standard-")) { const linkage = linkages.find(link => link.standardRowId === rowId); if (linkage) { linkedRowId = linkage.estimationRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } else if (rowId.startsWith("estimation-")) { const linkage = linkages.find(link => link.estimationRowId === rowId); if (linkage) { linkedRowId = linkage.standardRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } if (linkedRow) { const standardRowData = standardRowsData.find(data => data.id === rowId) || standardRowsData.find(data => data.id === linkedRowId); const estimationRowData = estimationRowsData.find(data => data.id === rowId) || estimationRowsData.find(data => data.id === linkedRowId); if (standardRowData.selection === "OFF" && estimationRowData.selection === "OFF") { console.log(`ID de la ligne standard : ${standardRowData.id}`); console.log(`ID de la ligne d'estimation : ${estimationRowData.id}`); standardRowData.selection = "ON"; estimationRowData.selection = "ON"; td.style.backgroundColor = "red"; linkedRow.cells[0].style.backgroundColor = "red"; // Mémorisez les identifiants dans objet_selection objet_selection.standardRowId = standardRowData.id; objet_selection.estimationRowId = estimationRowData.id; selectedRow = row; // Mettez à jour la ligne sélectionnée } else if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") { standardRowData.selection = "OFF"; estimationRowData.selection = "OFF"; td.style.backgroundColor = "white"; linkedRow.cells[0].style.backgroundColor = "white"; // Supprimez les identifiants de objet_selection delete objet_selection.standardRowId; delete objet_selection.estimationRowId; // Purgez toutes les variables et éléments utilisés pour gérer les fonctionnalités de sélection selection_origine = null; objet_up = {}; selectedRow = null; selectedRow = null; // Réinitialisez la ligne sélectionnée } } else { // Si aucune ligne liée n'est trouvée, vérifiez si une sélection est déjà en cours if (Object.keys(objet_selection).length > 0) { showMessageModal("Vous ne pouvez sélectionner qu'une seule ligne à la fois."); return; } } } function updateRowData(element) { const row = element.closest("tr"); const rowId = row.dataset.rowId; if (rowId.startsWith("standard-")) { let standardRowData = standardRowsData.find(data => data.id === rowId); if (!standardRowData) { standardRowData = { id: rowId, name: "", selectValue: "", count: "", cells: [], selection: "OFF" // TAG : SELECTION }; standardRowsData.push(standardRowData); } const cells = row.querySelectorAll("td"); standardRowData.name = cells[0].querySelector("input").value; standardRowData.selectValue = cells[1].querySelector("select").value; standardRowData.count = cells[2].textContent.trim(); standardRowData.cells = []; cells.forEach((cell, index) => { if (index > 2) { standardRowData.cells.push({ value: cell.dataset.cellValue, color: cell.dataset.cellColor }); } }); console.log(`Mise à jour de la ligne standard : ${rowId}`); } else if (rowId.startsWith("estimation-")) { let estimationRowData = estimationRowsData.find(data => data.id === rowId); if (!estimationRowData) { estimationRowData = { id: rowId, name: "", selectValue: "", estimationValue: "", selection: "OFF" // TAG : SELECTION }; estimationRowsData.push(estimationRowData); } const cells = row.querySelectorAll("td"); estimationRowData.name = cells[0].querySelector("input").value; estimationRowData.selectValue = cells[1].querySelector("select").value; estimationRowData.estimationValue = cells[2].querySelector("input").value; console.log(`Mise à jour de la ligne d'estimation : ${rowId}`); } else if (rowId.startsWith("special-")) { let specialRowData = specialRowsData.find(data => data.id === rowId); if (!specialRowData) { specialRowData = { id: rowId, name: "" }; specialRowsData.push(specialRowData); } specialRowData.name = row.querySelector("input").value; console.log(`Mise à jour de la ligne spéciale : ${rowId}`); } } function displayLinkages() { const debugOutputElement = document.getElementById("debugOutput"); debugOutputElement.textContent = JSON.stringify(linkages, null, 2); } function updateCountCell(row) { const countCell = row.cells[2]; const count = Array.from(row.cells).slice(3).filter(cell => cell.dataset.cellValue === "1").length; countCell.textContent = count; } function displaySpecialRowsData() { console.log("Contenu de specialRowsData :"); specialRowsData.forEach((rowData, index) => { console.log(`Ligne spéciale ${index + 1} :`, rowData); }); } function addSpecialRow(afterRow = null) { const newRow = document.createElement("tr"); newRow.classList.add("special-row"); newRow.setAttribute("draggable", "true"); newRow.dataset.rowId = `special-${generateRandomId()}`; newRow.title = newRow.dataset.rowId; // Ajoutez cette ligne const specialRowData = { id: newRow.dataset.rowId, name: `Ligne spéciale ${specialRowCounter}` }; const firstCell = document.createElement("td"); firstCell.classList.add("row-header"); const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = specialRowData.name; input.addEventListener("click", function (event) { event.stopPropagation(); input.focus(); input.style.width = "130px"; }); input.addEventListener("blur", function () { input.classList.remove("editing"); input.style.width = "65px"; updateRowData(input); }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { input.classList.remove("editing"); input.blur(); input.style.width = "65px"; updateRowData(input); } }); input.addEventListener("input", function () { updateRowData(input); }); const addButton = document.createElement("button"); addButton.classList.add("add-button"); addButton.textContent = "+"; addButton.addEventListener("click", function () { toggleCollapse(newRow); }); firstCell.appendChild(input); firstCell.appendChild(addButton); firstCell.addEventListener("contextmenu", function (event) { event.preventDefault(); showSpecialContextMenu(event, newRow); }); newRow.appendChild(firstCell); const mergedCell = document.createElement("td"); mergedCell.colSpan = 2; mergedCell.textContent = ""; newRow.appendChild(mergedCell); const td = document.createElement("td"); td.textContent = `Ligne spéciale ${specialRowCounter} - Détails`; td.colSpan = document.querySelector("thead tr:nth-child(2)").cells.length - 3; newRow.appendChild(td); if (afterRow) { tableBody.insertBefore(newRow, afterRow.nextSibling); } else { tableBody.appendChild(newRow); } newRow.addEventListener("dragstart", dragStart); newRow.addEventListener("dragover", dragOver); newRow.addEventListener("drop", drop); specialRowsData.push(specialRowData); // Ajouter l'objet dans le tableau dédié specialRowCounter++; // Afficher le contenu du tableau specialRowsData après l'ajout displaySpecialRowsData(); } function displayRowId(row) { const rowId = row.dataset.rowId; alert(`Identifiant de la ligne : ${rowId}`); } function toggleCollapse(specialRow) { const nextSpecialRow = getNextSpecialRow(specialRow); const rowsToToggle = []; let currentRow = specialRow.nextElementSibling; while (currentRow && currentRow !== nextSpecialRow) { if (!currentRow.classList.contains("special-row")) { rowsToToggle.push(currentRow); } currentRow = currentRow.nextElementSibling; } rowsToToggle.forEach(row => { row.classList.toggle("collapsed"); }); } function getNextSpecialRow(specialRow) { let currentRow = specialRow.nextElementSibling; while (currentRow) { if (currentRow.classList.contains("special-row")) { return currentRow; } currentRow = currentRow.nextElementSibling; } return null; } /* function showContextMenu(event, row) { contextMenu.innerHTML = ` <button class="dropdown-item" id="add-row">Ajouter une ligne</button> <button class="dropdown-item text-danger" id="delete-row">Supprimer cette ligne</button> <button class="dropdown-item" id="show-linkage">Afficher la liaison</button> `; contextMenu.style.top = `${event.clientY}px`; contextMenu.style.left = `${event.clientX}px`; contextMenu.style.display = "flex"; contextMenu.style.flexDirection = "column"; document.getElementById("add-row").addEventListener("click", function () { addRow(row); hideContextMenu(); }); document.getElementById("delete-row").addEventListener("click", function () { showConfirmationModal(row); hideContextMenu(); }); document.getElementById("show-linkage").addEventListener("click", function () { const linkage = linkages.find(link => link.standardRowId === row.dataset.rowId || link.estimationRowId === row.dataset.rowId); if (linkage) { alert(`Liaison trouvée :\nID: ${linkage.id}\nLigne standard: ${linkage.standardRowId}\nLigne estimation: ${linkage.estimationRowId}`); } else { alert("Aucune liaison trouvée pour cette ligne."); } hideContextMenu(); }); } */ /***************************************/ /* function showContextMenu(event, row) { contextMenu.innerHTML = ` <button class="dropdown-item" id="add-row">Ajouter une ligne</button> <button class="dropdown-item text-danger" id="delete-row">Supprimer cette ligne</button> <button class="dropdown-item" id="show-linkage">Afficher la liaison</button> <button class="dropdown-item" id="up-insert-special">UP</button> `; contextMenu.style.top = `${event.clientY}px`; contextMenu.style.left = `${event.clientX}px`; contextMenu.style.display = "flex"; contextMenu.style.flexDirection = "column"; document.getElementById("add-row").addEventListener("click", function () { addRow(row); hideContextMenu(); }); document.getElementById("delete-row").addEventListener("click", function () { showConfirmationModal(row); hideContextMenu(); }); document.getElementById("show-linkage").addEventListener("click", function () { const linkage = linkages.find(link => link.standardRowId === row.dataset.rowId || link.estimationRowId === row.dataset.rowId); if (linkage) { alert(`Liaison trouvée :\nID: ${linkage.id}\nLigne standard: ${linkage.standardRowId}\nLigne estimation: ${linkage.estimationRowId}`); } else { alert("Aucune liaison trouvée pour cette ligne."); } hideContextMenu(); }); document.getElementById("up-insert-special").addEventListener("click", function () { moveRowsUp(row); hideContextMenu(); }); } function moveRowsUp(row) { const rowId = row.dataset.rowId; let linkedRowId = null; let linkedRow = null; if (rowId.startsWith("standard-")) { const linkage = linkages.find(link => link.standardRowId === rowId); if (linkage) { linkedRowId = linkage.estimationRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } else if (rowId.startsWith("estimation-")) { const linkage = linkages.find(link => link.estimationRowId === rowId); if (linkage) { linkedRowId = linkage.standardRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } if (linkedRow) { const standardRowData = standardRowsData.find(data => data.id === rowId) || standardRowsData.find(data => data.id === linkedRowId); const estimationRowData = estimationRowsData.find(data => data.id === rowId) || estimationRowsData.find(data => data.id === linkedRowId); if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") { const previousRow = row.previousElementSibling; const previousLinkedRow = linkedRow.previousElementSibling; if (previousRow && previousLinkedRow) { const previousRowId = previousRow.dataset.rowId; const previousLinkedRowId = previousLinkedRow.dataset.rowId; const previousStandardRowData = standardRowsData.find(data => data.id === previousRowId) || standardRowsData.find(data => data.id === previousLinkedRowId); const previousEstimationRowData = estimationRowsData.find(data => data.id === previousRowId) || estimationRowsData.find(data => data.id === previousLinkedRowId); if (previousStandardRowData && previousEstimationRowData && previousStandardRowData.selection === "ON" && previousEstimationRowData.selection === "ON") { tableBody.insertBefore(row, previousRow); tableBody.insertBefore(linkedRow, previousLinkedRow); } else { alert("La ligne au-dessus n'est pas un couple de lignes standard et estimation sélectionnées."); } } else { alert("Aucune ligne au-dessus pour effectuer le déplacement."); } } else { alert("Les lignes doivent être sélectionnées pour être déplacées."); } } } */ /***************************************/ /* function showContextMenu(event, row) { contextMenu.innerHTML = ` <button class="dropdown-item" id="add-row">Ajouter une ligne</button> <button class="dropdown-item text-danger" id="delete-row">Supprimer cette ligne</button> <button class="dropdown-item" id="show-linkage">Afficher la liaison</button> <button class="dropdown-item" id="up-insert-special">UP</button> `; contextMenu.style.top = `${event.clientY}px`; contextMenu.style.left = `${event.clientX}px`; contextMenu.style.display = "flex"; contextMenu.style.flexDirection = "column"; document.getElementById("add-row").addEventListener("click", function () { addRow(row); hideContextMenu(); }); document.getElementById("delete-row").addEventListener("click", function () { showConfirmationModal(row); hideContextMenu(); }); document.getElementById("show-linkage").addEventListener("click", function () { const linkage = linkages.find(link => link.standardRowId === row.dataset.rowId || link.estimationRowId === row.dataset.rowId); if (linkage) { alert(`Liaison trouvée :\nID: ${linkage.id}\nLigne standard: ${linkage.standardRowId}\nLigne estimation: ${linkage.estimationRowId}`); } else { alert("Aucune liaison trouvée pour cette ligne."); } hideContextMenu(); }); document.getElementById("up-insert-special").addEventListener("click", function () { moveRowsUp(row); hideContextMenu(); }); } function moveRowsUp(row) { const rowId = row.dataset.rowId; let linkedRowId = null; let linkedRow = null; if (rowId.startsWith("standard-")) { const linkage = linkages.find(link => link.standardRowId === rowId); if (linkage) { linkedRowId = linkage.estimationRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } else if (rowId.startsWith("estimation-")) { const linkage = linkages.find(link => link.estimationRowId === rowId); if (linkage) { linkedRowId = linkage.standardRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } if (linkedRow) { const standardRowData = standardRowsData.find(data => data.id === rowId) || standardRowsData.find(data => data.id === linkedRowId); const estimationRowData = estimationRowsData.find(data => data.id === rowId) || estimationRowsData.find(data => data.id === linkedRowId); if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") { const rowsAbove = []; let currentRow = row.previousElementSibling; while (currentRow) { rowsAbove.push(currentRow); currentRow = currentRow.previousElementSibling; } // Afficher la liste des lignes au-dessus console.log("Lignes au-dessus :"); rowsAbove.forEach(aboveRow => { console.log(`ID: ${aboveRow.dataset.rowId}, Type: ${aboveRow.dataset.rowId.startsWith("standard-") ? "Standard" : "Estimation"}`); }); // Vous pouvez également afficher cette liste dans une boîte modale ou dans une autre interface utilisateur si nécessaire } else { alert("Les lignes doivent être sélectionnées pour être déplacées."); } } } */ function showContextMenu(event, row) { contextMenu.innerHTML = ` <button class="dropdown-item" id="add-row">Ajouter une ligne</button> <button class="dropdown-item text-danger" id="delete-row">Supprimer cette ligne</button> <button class="dropdown-item" id="show-linkage">Afficher la liaison</button> <button class="dropdown-item" id="up-insert-special">UP</button> `; contextMenu.style.top = `${event.clientY}px`; contextMenu.style.left = `${event.clientX}px`; contextMenu.style.display = "flex"; contextMenu.style.flexDirection = "column"; document.getElementById("add-row").addEventListener("click", function () { addRow(row); hideContextMenu(); }); document.getElementById("delete-row").addEventListener("click", function () { showConfirmationModal(row); hideContextMenu(); }); document.getElementById("show-linkage").addEventListener("click", function () { const linkage = linkages.find(link => link.standardRowId === row.dataset.rowId || link.estimationRowId === row.dataset.rowId); if (linkage) { alert(`Liaison trouvée :\nID: ${linkage.id}\nLigne standard: ${linkage.standardRowId}\nLigne estimation: ${linkage.estimationRowId}`); } else { alert("Aucune liaison trouvée pour cette ligne."); } hideContextMenu(); }); document.getElementById("up-insert-special").addEventListener("click", function () { moveRowsUp(row); hideContextMenu(); }); } function moveRowsUp(row) { const rowId = row.dataset.rowId; let linkedRowId = null; let linkedRow = null; if (rowId.startsWith("standard-")) { const linkage = linkages.find(link => link.standardRowId === rowId); if (linkage) { linkedRowId = linkage.estimationRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } else if (rowId.startsWith("estimation-")) { const linkage = linkages.find(link => link.estimationRowId === rowId); if (linkage) { linkedRowId = linkage.standardRowId; linkedRow = document.querySelector(`tr[data-row-id="${linkedRowId}"]`); } } if (linkedRow) { const standardRowData = standardRowsData.find(data => data.id === rowId) || standardRowsData.find(data => data.id === linkedRowId); const estimationRowData = estimationRowsData.find(data => data.id === rowId) || estimationRowsData.find(data => data.id === linkedRowId); if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") { // Afficher le contenu de objet_selection dans la console console.log("Contenu de objet_selection :", objet_selection); const rowsAbove = []; let currentRow = row.previousElementSibling; while (currentRow) { rowsAbove.push(currentRow); currentRow = currentRow.previousElementSibling; } // Afficher la liste des lignes au-dessus console.log("Lignes au-dessus :"); rowsAbove.forEach(aboveRow => { const aboveRowId = aboveRow.dataset.rowId; let rowType = "Inconnu"; if (aboveRowId.startsWith("standard-")) { rowType = "Standard"; } else if (aboveRowId.startsWith("estimation-")) { rowType = "Estimation"; } else if (aboveRowId.startsWith("special-")) { rowType = "Special"; } console.log(`ID: ${aboveRowId}, Type: ${rowType}`); }); // Vous pouvez également afficher cette liste dans une boîte modale ou dans une autre interface utilisateur si nécessaire } else { alert("Les lignes doivent être sélectionnées pour être déplacées."); } } } /**************************************/ function insertSpecialRow(direction, row) { const newSpecialRow = document.createElement("tr"); newSpecialRow.classList.add("special-row"); newSpecialRow.setAttribute("draggable", "true"); newSpecialRow.dataset.rowId = `special-${generateRandomId()}`; newSpecialRow.title = newSpecialRow.dataset.rowId; const firstCell = document.createElement("td"); firstCell.classList.add("row-header"); const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = `Ligne spéciale`; input.addEventListener("click", function (event) { event.stopPropagation(); input.focus(); input.style.width = "130px"; }); input.addEventListener("blur", function () { input.classList.remove("editing"); input.style.width = "65px"; updateRowData(input); }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { input.classList.remove("editing"); input.blur(); input.style.width = "65px"; updateRowData(input); } }); input.addEventListener("input", function () { updateRowData(input); }); const addButton = document.createElement("button"); addButton.classList.add("add-button"); addButton.textContent = "+"; addButton.addEventListener("click", function () { toggleCollapse(newSpecialRow); }); firstCell.appendChild(input); firstCell.appendChild(addButton); firstCell.addEventListener("contextmenu", function (event) { event.preventDefault(); showSpecialContextMenu(event, newSpecialRow); }); newSpecialRow.appendChild(firstCell); const mergedCell = document.createElement("td"); mergedCell.colSpan = 2; mergedCell.textContent = ""; newSpecialRow.appendChild(mergedCell); const td = document.createElement("td"); td.textContent = `Ligne spéciale - Détails`; td.colSpan = document.querySelector("thead tr:nth-child(2)").cells.length - 3; newSpecialRow.appendChild(td); if (direction === "up") { tableBody.insertBefore(newSpecialRow, row); } else if (direction === "down") { tableBody.insertBefore(newSpecialRow, row.nextSibling); } newSpecialRow.addEventListener("dragstart", dragStart); newSpecialRow.addEventListener("dragover", dragOver); newSpecialRow.addEventListener("drop", drop); specialRowsData.push({ id: newSpecialRow.dataset.rowId, name: input.value }); // Afficher le contenu du tableau specialRowsData après l'ajout displaySpecialRowsData(); } function showSpecialContextMenu(event, row) { specialContextMenu.innerHTML = ` <button class="dropdown-item" id="add-special-row">Ajouter une ligne spéciale</button> <button class="dropdown-item text-danger" id="delete-special-row">Supprimer cette ligne</button> <label class="dropdown-item"> <input type="checkbox" id="special-checkbox"> Attacher </label> `; specialContextMenu.style.top = `${event.clientY}px`; specialContextMenu.style.left = `${event.clientX}px`; specialContextMenu.style.display = "flex"; specialContextMenu.style.flexDirection = "column"; const checkbox = document.getElementById("special-checkbox"); const rowId = row.dataset.rowId; let hasStandardRowsBelow = false; let currentRow = row.nextElementSibling; const standardRows = []; while (currentRow && !currentRow.classList.contains("special-row")) { if (!currentRow.classList.contains("special-row")) { hasStandardRowsBelow = true; standardRows.push(currentRow); } currentRow = currentRow.nextElementSibling; } if (hasStandardRowsBelow) { checkbox.disabled = false; } else { checkbox.disabled = true; checkbox.checked = false; } if (specialRowStates[rowId]) { checkbox.checked = specialRowStates[rowId].checked; } checkbox.addEventListener("change", function () { specialRowStates[rowId] = { checked: checkbox.checked, rows: standardRows }; standardRows.forEach(standardRow => { const firstCell = standardRow.querySelector("td:first-child"); if (checkbox.checked) { firstCell.style.backgroundColor = "yellow"; standardRow.classList.add("no-drag"); } else { firstCell.style.backgroundColor = ""; standardRow.classList.remove("no-drag"); } }); if (checkbox.checked) { associations[rowId] = standardRows.map(row => row.dataset.rowId); } else { delete associations[rowId]; } console.log(`Lignes standards concernées : ${standardRows.map(row => row.rowIndex).join(", ")}`); }); document.getElementById("add-special-row").addEventListener("click", function () { addSpecialRow(row); hideSpecialContextMenu(); }); document.getElementById("delete-special-row").addEventListener("click", function () { showConfirmationModal(row); hideSpecialContextMenu(); }); } function showColorContextMenu(event, cell) { colorContextMenu.style.top = `${event.clientY}px`; colorContextMenu.style.left = `${event.clientX}px`; colorContextMenu.style.display = "flex"; colorContextMenu.style.flexDirection = "column"; document.querySelectorAll(".selected-cell").forEach(c => c.classList.remove("selected-cell")); cell.classList.add("selected-cell"); } function displayStandardRowsData() { console.log("Contenu de standardRowsData :"); standardRowsData.forEach((rowData, index) => { console.log(`Ligne ${index + 1} :`, rowData); }); } function displayEstimationRowsData() { console.log("Contenu de estimationRowsData :"); estimationRowsData.forEach((rowData, index) => { console.log(`Ligne ${index + 1} :`, rowData); }); } function displaySpecialRowsData() { console.log("Contenu de specialRowsData :"); specialRowsData.forEach((rowData, index) => { console.log(`Ligne ${index + 1} :`, rowData); }); } function displayLinkagesData() { console.log("Contenu de LinkagesData :"); linkages.forEach((rowData, index) => { console.log(`Ligne ${index + 1} :`, rowData); }); } function showMessageModal(message) { const modal = new bootstrap.Modal(document.getElementById('messageModal')); const modalBody = document.getElementById('messageModalBody'); modalBody.textContent = message; modal.show(); } document.addEventListener("click", function (event) { if (!contextMenu.contains(event.target)) { hideContextMenu(); } if (!specialContextMenu.contains(event.target)) { hideSpecialContextMenu(); } if (!colorContextMenu.contains(event.target)) { hideColorContextMenu(); } const inputs = document.querySelectorAll(".editable-input"); inputs.forEach(input => { if (!input.contains(event.target)) { input.classList.remove("editing"); } }); }); document.addEventListener("keydown", function (event) { if (event.key === "Escape") { hideContextMenu(); hideSpecialContextMenu(); hideColorContextMenu(); } }); function hideContextMenu() { contextMenu.style.display = "none"; } function hideSpecialContextMenu() { specialContextMenu.style.display = "none"; } function hideColorContextMenu() { colorContextMenu.style.display = "none"; } document.getElementById("addRowButton").addEventListener("click", addRow); document.getElementById("addSpecialRowButton").addEventListener("click", addSpecialRow); document.querySelectorAll("tbody tr td:first-child").forEach(td => { td.addEventListener("contextmenu", function (event) { event.preventDefault(); showContextMenu(event, td.parentElement); }); }); function dragStart(event) { const row = event.target.closest("tr"); if (row.classList.contains("no-drag")) { event.preventDefault(); return; } event.dataTransfer.setData("text/plain", row.rowIndex); row.classList.add("dragging"); } function dragOver(event) { event.preventDefault(); const draggingRow = document.querySelector(".dragging"); const targetRow = event.target.closest("tr"); if (targetRow && draggingRow !== targetRow && !targetRow.classList.contains("no-drag")) { const rect = targetRow.getBoundingClientRect(); const offset = rect.top + (rect.height / 2); if (event.clientY - offset > 0) { tableBody.insertBefore(draggingRow, targetRow.nextSibling); } else { tableBody.insertBefore(draggingRow, targetRow); } } } function drop(event) { event.preventDefault(); const draggingRow = document.querySelector(".dragging"); draggingRow.classList.remove("dragging"); if (draggingRow.classList.contains("special-row")) { const specialRowId = draggingRow.dataset.rowId; if (associations[specialRowId]) { const associatedRowIds = associations[specialRowId]; associatedRowIds.forEach(rowId => { const associatedRow = document.querySelector(`tr[data-row-id="${rowId}"]`); if (associatedRow) { tableBody.insertBefore(associatedRow, draggingRow.nextSibling); } }); } } } function showConfirmationModal(row) { const modal = new bootstrap.Modal(document.getElementById('confirmationModal')); modal.show(); document.getElementById('confirmDelete').addEventListener('click', function () { let linkageIndex = -1; const rowId = row.dataset.rowId; const isStandardRow = rowId.startsWith("standard-"); const isEstimationRow = rowId.startsWith("estimation-"); const isSpecialRow = rowId.startsWith("special-"); if (isStandardRow) { linkageIndex = linkages.findIndex(link => link.standardRowId === rowId); } else if (isEstimationRow) { linkageIndex = linkages.findIndex(link => link.estimationRowId === rowId); } else if (isSpecialRow) { linkageIndex = linkages.findIndex(link => link.specialRowId === rowId); } if (linkageIndex !== -1) { const linkage = linkages[linkageIndex]; console.log("Liaison trouvée :"); console.log("Index de la liaison :", linkageIndex); // Afficher l'indice de la liaison console.log("ID de la liaison :", linkage.id); console.log("ID de la ligne standard :", linkage.standardRowId); console.log("ID de la ligne d'estimation :", linkage.estimationRowId); } let standardRowId = null; let estimationRowId = null; let linkageId = null; if (isStandardRow) { standardRowId = rowId; const linkage = linkages.find(link => link.standardRowId === standardRowId); if (linkage) { estimationRowId = linkage.estimationRowId; linkageId = linkage.id; } } else if (isEstimationRow) { estimationRowId = rowId; const linkage = linkages.find(link => link.estimationRowId === estimationRowId); if (linkage) { standardRowId = linkage.standardRowId; linkageId = linkage.id; } } else if (isSpecialRow) { // Handle special row deletion if needed } if (standardRowId && estimationRowId && linkageId) { // Remove the corresponding sub-arrays in tableData const tableData = traceTable(); const standardIndex = tableData.findIndex(item => item.id === standardRowId); const estimationIndex = tableData.findIndex(item => item.id === estimationRowId); const linkageIndex = tableData.findIndex(item => item.id === linkageId); if (standardIndex !== -1) { tableData.splice(standardIndex, 1); } if (estimationIndex !== -1) { tableData.splice(estimationIndex, 1); } if (linkageIndex !== -1) { tableData.splice(linkageIndex, 1); } // Remove the rows from the DOM const standardRow = document.querySelector(`tr[data-row-id="${standardRowId}"]`); const estimationRow = document.querySelector(`tr[data-row-id="${estimationRowId}"]`); if (standardRow) { standardRow.remove(); } if (estimationRow) { estimationRow.remove(); } // Update the linkages array const linkageIndexInLinkages = linkages.findIndex(link => link.id === linkageId); if (linkageIndexInLinkages !== -1) { linkages.splice(linkageIndexInLinkages, 1); } // Display the updated tableData displayJSONData(tableData); } modal.hide(); }); document.getElementById('cancelDelete').addEventListener('click', function () { modal.hide(); }); } function regenerateTableAfterDeletion_bis() { // Effacer le contenu actuel du tableau tableBody.innerHTML = ""; // Parcourir les liaisons pour recréer les lignes linkages.forEach(linkage => { // Trouver les données correspondantes pour les lignes standard et d'estimation const standardRowData = standardRowsData.find(row => row.id === linkage.standardRowId); const estimationRowData = estimationRowsData.find(row => row.id === linkage.estimationRowId); const specialRowData = specialRowsData.find(row => row.id === linkage.specialRowId); // Créer une nouvelle ligne standard const standardRow = document.createElement("tr"); standardRow.setAttribute("draggable", "true"); standardRow.dataset.rowId = standardRowData.id; // Ajouter les cellules pour la ligne standard const firstCells = [standardRowData.name, "", standardRowData.count]; firstCells.forEach((text, index) => { const td = document.createElement("td"); td.dataset.cellId = `cell-${standardRowData.id}-${index}`; if (index === 0) { const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = standardRowData.name; input.addEventListener("click", function (event) { event.stopPropagation(); input.focus(); input.style.width = "130px"; }); input.addEventListener("blur", function () { if (!keydownHandled && !alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } keydownHandled = false; alertShown = false; }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { keydownHandled = true; if (!alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } } }); td.appendChild(input); } else if (index === 1) { const select = document.createElement("select"); for (let i = 1; i <= 10; i++) { const option = document.createElement("option"); option.value = i; option.textContent = `Option ${i}`; select.appendChild(option); } select.value = standardRowData.selectValue; select.addEventListener("change", function () { updateRowData(select); }); td.appendChild(select); } else { td.textContent = text; } if (index === 0) { td.classList.add("row-header"); td.addEventListener("click", function (event) { event.preventDefault(); handleRowClick(standardRow, td); // TAG : SELECTION }); td.addEventListener("contextmenu", function (event) { event.preventDefault(); showContextMenu(event, standardRow); }); } standardRow.appendChild(td); }); // Ajouter les cellules de jours ouvrés const headerCells = document.querySelectorAll("thead tr:nth-child(2) th:not(.weekend):not(.holiday)"); const workingDaysCount = headerCells.length; for (let i = 0; i < workingDaysCount - 3; i++) { const td = document.createElement("td"); td.dataset.cellId = `cell-${standardRowData.id}-${i}`; td.dataset.cellValue = standardRowData.cells[i].value; td.dataset.cellColor = standardRowData.cells[i].color; td.textContent = standardRowData.cells[i].value; td.style.backgroundColor = standardRowData.cells[i].color; td.addEventListener("click", function () { const newValue = td.dataset.cellValue === "0" ? "1" : "0"; td.dataset.cellValue = newValue; td.textContent = newValue; td.style.backgroundColor = newValue === "1" ? "green" : "white"; td.dataset.cellColor = newValue === "1" ? "green" : "white"; updateCountCell(standardRow); updateRowData(td); }); td.addEventListener("contextmenu", function (event) { event.preventDefault(); if (td.dataset.cellValue === "1") { showColorContextMenu(event, td); } }); td.title = `ID: ${td.dataset.cellId}`; standardRow.appendChild(td); } // Ajouter la ligne standard au tableau tableBody.appendChild(standardRow); // Ajouter les événements de drag-and-drop standardRow.addEventListener("dragstart", dragStart); standardRow.addEventListener("dragover", dragOver); standardRow.addEventListener("drop", drop); // Créer une nouvelle ligne d'estimation const estimationRow = document.createElement("tr"); estimationRow.setAttribute("draggable", "true"); estimationRow.dataset.rowId = estimationRowData.id; estimationRow.classList.add("estimation-row"); // Ajouter les cellules pour la ligne d'estimation const estimationFirstCells = [estimationRowData.name, "", estimationRowData.estimationValue]; estimationFirstCells.forEach((text, index) => { const td = document.createElement("td"); td.dataset.cellId = `cell-${estimationRowData.id}-${index}`; if (index === 0) { const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = estimationRowData.name; input.addEventListener("click", function (event) { event.stopPropagation(); input.focus(); input.style.width = "130px"; }); input.addEventListener("blur", function () { if (!keydownHandled && !alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } keydownHandled = false; alertShown = false; }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { keydownHandled = true; if (!alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } } }); td.appendChild(input); } else if (index === 1) { const select = document.createElement("select"); for (let i = 1; i <= 10; i++) { const option = document.createElement("option"); option.value = i; option.textContent = `Option ${i}`; select.appendChild(option); } select.value = estimationRowData.selectValue; select.addEventListener("change", function () { updateRowData(select); }); td.appendChild(select); } else { const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = text; input.addEventListener("blur", function () { const value = parseInt(input.value, 10); if (isNaN(value) || value < 1 || value > 365) { input.value = "1"; showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365."); } else { updateRowData(input); } }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { const value = parseInt(input.value, 10); if (isNaN(value) || value < 1 || value > 365) { input.value = "1"; showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365."); } else { updateRowData(input); } input.classList.remove("editing"); input.blur(); input.style.width = "65px"; } }); td.appendChild(input); } if (index === 0) { td.classList.add("row-header"); td.addEventListener("click", function (event) { event.preventDefault(); handleRowClick(estimationRow, td); // TAG : SELECTION }); td.addEventListener("contextmenu", function (event) { event.preventDefault(); showContextMenu(event, estimationRow); }); } estimationRow.appendChild(td); }); const mergedCell = document.createElement("td"); mergedCell.colSpan = document.querySelector("thead tr:nth-child(2)").cells.length - 3; mergedCell.textContent = ""; mergedCell.classList.add("no-click"); estimationRow.appendChild(mergedCell); // Ajouter la ligne d'estimation au tableau tableBody.appendChild(estimationRow); // Ajouter les événements de drag-and-drop estimationRow.addEventListener("dragstart", dragStart); estimationRow.addEventListener("dragover", dragOver); estimationRow.addEventListener("drop", drop); // Créer une nouvelle ligne spéciale if (specialRowData) { const specialRow = document.createElement("tr"); specialRow.classList.add("special-row"); specialRow.setAttribute("draggable", "true"); specialRow.dataset.rowId = specialRowData.id; const firstCell = document.createElement("td"); firstCell.classList.add("row-header"); const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = specialRowData.name; input.addEventListener("click", function (event) { event.stopPropagation(); input.focus(); input.style.width = "130px"; }); input.addEventListener("blur", function () { input.classList.remove("editing"); input.style.width = "65px"; updateRowData(input); }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { input.classList.remove("editing"); input.blur(); input.style.width = "65px"; updateRowData(input); } }); input.addEventListener("input", function () { updateRowData(input); }); const addButton = document.createElement("button"); addButton.classList.add("add-button"); addButton.textContent = "+"; addButton.addEventListener("click", function () { toggleCollapse(specialRow); }); firstCell.appendChild(input); firstCell.appendChild(addButton); firstCell.addEventListener("contextmenu", function (event) { event.preventDefault(); showSpecialContextMenu(event, specialRow); }); specialRow.appendChild(firstCell); const mergedCell = document.createElement("td"); mergedCell.colSpan = 2; mergedCell.textContent = ""; specialRow.appendChild(mergedCell); const td = document.createElement("td"); td.textContent = `${specialRowData.name} - Détails`; td.colSpan = document.querySelector("thead tr:nth-child(2)").cells.length - 3; specialRow.appendChild(td); tableBody.appendChild(specialRow); specialRow.addEventListener("dragstart", dragStart); specialRow.addEventListener("dragover", dragOver); specialRow.addEventListener("drop", drop); } }); // Afficher les liaisons dans la console displayLinkages(); } function showMessageModal(message) { const modal = new bootstrap.Modal(document.getElementById('messageModal')); const modalBody = document.getElementById('messageModalBody'); modalBody.textContent = message; modal.show(); } document.addEventListener("keydown", function (event) { if (event.key === "Escape") { hideContextMenu(); hideSpecialContextMenu(); hideColorContextMenu(); } }); function hideContextMenu() { contextMenu.style.display = "none"; } function hideSpecialContextMenu() { specialContextMenu.style.display = "none"; } function hideColorContextMenu() { colorContextMenu.style.display = "none"; } document.getElementById("addRowButton").addEventListener("click", addRow); document.getElementById("addSpecialRowButton").addEventListener("click", addSpecialRow); document.querySelectorAll("tbody tr td:first-child").forEach(td => { td.addEventListener("contextmenu", function (event) { event.preventDefault(); showContextMenu(event, td.parentElement); }); }); function query() { const tableData = []; const rows = tableBody.querySelectorAll("tr"); rows.forEach(row => { const rowData = {}; const cells = row.querySelectorAll("td"); if (row.dataset.rowId.startsWith("special-")) { const inputCell = cells[0]; const inputValue = inputCell.querySelector("input").value; rowData.id = row.dataset.rowId; rowData.name = inputValue; } else if (row.dataset.rowId.startsWith("estimation-")) { const inputCell = cells[0]; const inputValue = inputCell.querySelector("input").value; rowData.id = row.dataset.rowId; rowData.name = inputValue; rowData.estimationValue = cells[2].querySelector("input").value; rowData.selectValue = cells[1].querySelector("select").value; rowData.selection = cells[0].style.backgroundColor === "red" ? "ON" : "OFF"; // TAG : SELECTION } else { rowData.id = row.dataset.rowId; rowData.name = cells[0].querySelector("input").value; rowData.selectValue = cells[1].querySelector("select").value; rowData.count = cells[2].textContent.trim(); rowData.selection = cells[0].style.backgroundColor === "red" ? "ON" : "OFF"; // TAG : SELECTION //rowData.cells = []; /*cells.forEach((cell, index) => { if (index > 2) { rowData.cells.push({ value: cell.dataset.cellValue, color: cell.dataset.cellColor }); } });*/ } tableData.push(rowData); }); // Ajouter les objets linkage au tableau de données linkages.forEach(linkage => { tableData.push({ id: linkage.id, standardRowId: linkage.standardRowId, estimationRowId: linkage.estimationRowId }); }); //return tableData; //const tableData = traceTable(); console.log("Données retournées par traceTable():", JSON.stringify(tableData, null, 2)); } function traceTable() { const tableData = []; const rows = tableBody.querySelectorAll("tr"); // Parcourir chaque ligne du tableau et récupérer les données des cellules rows.forEach(row => { const rowData = {}; const cells = row.querySelectorAll("td"); if (row.dataset.rowId.startsWith("special-")) { const inputCell = cells[0]; const inputValue = inputCell.querySelector("input").value; rowData.id = row.dataset.rowId; rowData.name = inputValue; } else if (row.dataset.rowId.startsWith("estimation-")) { const inputCell = cells[0]; const inputValue = inputCell.querySelector("input").value; rowData.id = row.dataset.rowId; rowData.name = inputValue; rowData.estimationValue = cells[2].querySelector("input").value; rowData.selectValue = cells[1].querySelector("select").value; rowData.selection = cells[0].style.backgroundColor === "red" ? "ON" : "OFF"; // TAG : SELECTION } else { rowData.id = row.dataset.rowId; rowData.name = cells[0].querySelector("input").value; rowData.selectValue = cells[1].querySelector("select").value; rowData.count = cells[2].textContent.trim(); rowData.cells = []; rowData.selection = cells[0].style.backgroundColor === "red" ? "ON" : "OFF"; // TAG : SELECTION cells.forEach((cell, index) => { if (index > 2) { rowData.cells.push({ value: cell.dataset.cellValue, color: cell.dataset.cellColor }); } }); } tableData.push(rowData); }); // Ajouter les objets linkage au tableau de données linkages.forEach(linkage => { tableData.push({ id: linkage.id, standardRowId: linkage.standardRowId, estimationRowId: linkage.estimationRowId }); }); return tableData; } function openRangeSelectionModal(cell) { const modal = new bootstrap.Modal(document.getElementById('rangeSelectionModal')); const startCellIdInput = document.getElementById('startCellId'); const endCellIdInput = document.getElementById('endCellId'); const rangeResult = document.getElementById('rangeResult'); const rangeComboBox = document.getElementById('rangeComboBox'); rangeComboBox.innerHTML = ""; for (let i = 1; i <= 50; i++) { const option = document.createElement("option"); option.value = i; option.textContent = i; rangeComboBox.appendChild(option); } rangeComboBox.addEventListener("change", function () { const startCellId = startCellIdInput.value; const startParts = startCellId.split('-'); const startNumber = parseInt(startParts[2], 10); const comboValue = parseInt(rangeComboBox.value, 10); const totalDays = startNumber + comboValue; const endCellId = `${startParts[0]}-${startParts[1]}-${totalDays}`; console.log("Valeur sélectionnée :", comboValue); console.log("Nb jours :", totalDays); rangeResult.textContent = `Nb jours : ${totalDays}`; endCellIdInput.value = endCellId; }); startCellIdInput.value = cell.dataset.cellId; endCellIdInput.value = ""; rangeResult.textContent = "Nb jours : 0"; modal.show(); document.getElementById('confirmRangeSelection').addEventListener('click', function () { const startCellId = startCellIdInput.value; const endCellId = endCellIdInput.value; const comboValue = rangeComboBox.value; alert(startCellId + " " + endCellId); updateCellRange(startCellId, endCellId, comboValue); modal.hide(); }); document.getElementById('cancelRangeSelection').addEventListener('click', function () { modal.hide(); }); const modalHeader = modal._dialog.querySelector('.modal-header'); let isDragging = false; let offsetX, offsetY; modalHeader.addEventListener('mousedown', function (event) { isDragging = true; offsetX = event.clientX - modal._dialog.offsetLeft; offsetY = event.clientY - modal._dialog.offsetTop; modal._dialog.style.pointerEvents = 'none'; }); document.addEventListener('mousemove', function (event) { if (isDragging) { modal._dialog.style.left = `${event.clientX - offsetX}px`; modal._dialog.style.top = `${event.clientY - offsetY}px`; } }); document.addEventListener('mouseup', function () { isDragging = false; modal._dialog.style.pointerEvents = 'all'; }); endCellIdInput.addEventListener('input', function () { const startParts = startCellIdInput.value.split('-'); const endParts = endCellIdInput.value.split('-'); if (startParts.length === 3 && endParts.length === 3 && startParts[0] === endParts[0] && startParts[1] === endParts[1]) { const startValue = parseInt(startParts[2], 10); const endValue = parseInt(endParts[2], 10); console.log(" ++ " + startValue + " " + endValue); const result = endValue - startValue; rangeResult.textContent = `Nb jours : ${result} jours`; if (result > 0) { alert(`Nb jours : ${result} jours`); } } else { rangeResult.textContent = "Nb jours : 0"; } }); } function updateCellRange(startCellId, endCellId) { const startCell = document.querySelector(`td[data-cell-id="${startCellId}"]`); const endCell = document.querySelector(`td[data-cell-id="${endCellId}"]`); if (startCell && endCell && startCell.parentElement === endCell.parentElement) { const startIndex = Array.from(startCell.parentElement.cells).indexOf(startCell); const endIndex = Array.from(endCell.parentElement.cells).indexOf(endCell); for (let i = startIndex; i <= endIndex; i++) { const cell = startCell.parentElement.cells[i]; cell.dataset.cellValue = "1"; cell.textContent = "1"; cell.style.backgroundColor = "green"; cell.dataset.cellColor = "green"; updateRowData(cell); } updateCountCell(startCell.parentElement); } else { showMessageModal("Les cellules doivent être sur la même ligne."); } } tableBody.addEventListener("mouseover", function (event) { const cell = event.target.closest("td"); if (cell) { currentCell = cell; } }); document.addEventListener("keydown", function (event) { if (event.key === "p" && currentCell) { openRangeSelectionModal(currentCell); } }); document.getElementById("buildButton").addEventListener("click", function () { console.log("Build ..."); //logRowTypes(); Jsondata(); //const tableData = traceTable(); //console.log("Building data... " + tableData); }); function aaaaquery() { const tableData = traceTable(); console.log("Données retournées par traceTable():", JSON.stringify(tableData, null, 2)); } function Jsondata() { const jsonData = []; const rows = document.querySelectorAll("tbody tr"); rows.forEach(row => { const rowId = row.dataset.rowId; const cells = row.querySelectorAll("td"); if (rowId.startsWith("standard-")) { const standardRow = { id: rowId, name: cells[0].querySelector("input").value, selectValue: cells[1].querySelector("select").value, count: cells[2].textContent.trim(), cells: [], selection: cells[0].style.backgroundColor === "red" ? "ON" : "OFF" // TAG : SELECTION }; cells.forEach((cell, index) => { if (index > 2) { standardRow.cells.push({ value: cell.dataset.cellValue, color: cell.dataset.cellColor }); } }); jsonData.push(standardRow); } else if (rowId.startsWith("estimation-")) { const estimationRow = { id: rowId, name: cells[0].querySelector("input").value, selectValue: cells[1].querySelector("select").value, estimationValue: cells[2].querySelector("input").value, selection: cells[0].style.backgroundColor === "red" ? "ON" : "OFF" // TAG : SELECTION }; jsonData.push(estimationRow); } else if (rowId.startsWith("special-")) { const specialRow = { id: rowId, name: cells[0].querySelector("input").value }; jsonData.push(specialRow); } }); // Ajouter les objets linkage linkages.forEach(linkage => { jsonData.push({ id: linkage.id, standardRowId: linkage.standardRowId, estimationRowId: linkage.estimationRowId }); }); console.log(JSON.stringify(jsonData, null, 2)); sendDataToPHP(jsonData); } function logRowTypes() { console.log("TRACE Start"); const rowDataArray = []; const rows = tableBody.querySelectorAll("tr"); const rowTypes = { standard: 0, estimation: 0, special: 0 }; linkages.forEach((linkage, index) => { rowDataArray.push(linkage); }); rows.forEach(row => { const rowId = row.dataset.rowId; if (rowId.startsWith("standard-")) { rowTypes.standard++; } else if (rowId.startsWith("estimation-")) { rowTypes.estimation++; } else if (rowId.startsWith("special-")) { rowTypes.special++; } let rowData = null; if (rowId.startsWith("standard-")) { rowData = standardRowsData.find(data => data.id === rowId); } else if (rowId.startsWith("estimation-")) { rowData = estimationRowsData.find(data => data.id === rowId); } else if (rowId.startsWith("special-")) { rowData = specialRowsData.find(data => data.id === rowId); } if (rowData) { console.log("Identifiant de la ligne :", rowId); console.log("Détails de l'objet :", rowData); rowDataArray.push(rowData); } else { console.log("Aucune donnée trouvée pour l'identifiant de la ligne :", rowId); } }); linkages.forEach((linkage, index) => { console.log(`Liaison ${index + 1} :`, linkage); }); console.log("Nombre de lignes standard :", rowTypes.standard); console.log("Nombre de lignes d'estimation :", rowTypes.estimation); console.log("Nombre de lignes spéciales :", rowTypes.special); sendDataToPHP(rowDataArray); console.log("TRACE end"); } function sendDataToPHP(rowDataArray) { // Afficher les données dans la console console.log("Données envoyées à PHP :", rowDataArray); // Envoyer les données au script PHP fetch('script_export.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(rowDataArray) }) .then(response => response.json()) .then(data => { // Gérer les différents types de messages renvoyés if (data.status === 'success') { console.log('Succès :', data.message); showMessageModal(data.message); } else if (data.status === 'error') { console.error('Erreur :', data.message); showMessageModal(data.message); } else { console.error('Réponse inattendue :', data); showMessageModal('Réponse inattendue du serveur.'); } }) .catch(error => { console.error('Erreur :', error); showMessageModal('Une erreur est survenue lors de l\'envoi des données.'); }); } document.getElementById("blablaButton").addEventListener("click", fetchJsonData); function fetchJsonData() { // Envoyer une requête GET au script PHP fetch('script_import.php') .then(response => response.json()) .then(data => { // Gérer les différents types de messages renvoyés if (data.status === 'success') { //console.log("<--------------- Début file.json --------------------->"); //console.log('Données JSON récupérées :', data.data); // Parcourir chaque élément (sous-tableau JSON) de data data.data.forEach((item, index) => { //console.log("<------------------------------------>"); //console.log(`Élément ${index + 1} :`); if (item.id.includes('standard')) { //console.log('Détails de la ligne standard :'); for (const key in item) { if (item.hasOwnProperty(key)) { if (key === 'cells' && Array.isArray(item[key])) { //console.log(` ${key}:`); /* pas utile de voir le détail de chaque cellule item[key].forEach((cell, cellIndex) => { console.log(` Cell ${cellIndex + 1}:`); for (const cellKey in cell) { if (cell.hasOwnProperty(cellKey)) { console.log(` ${cellKey}: ${cell[cellKey]}`); } } });*/ } else { // console.log(` ${key}: ${item[key]}`); } } } } else if (item.id.includes('estimation')) { //console.log('Détails de la ligne d\'estimation :'); for (const key in item) { if (item.hasOwnProperty(key)) { //console.log(` ${key}: ${item[key]}`); } } } else if (item.id.includes('special')) { //console.log('Détails de la ligne spéciale :'); for (const key in item) { if (item.hasOwnProperty(key)) { //console.log(` ${key}: ${item[key]}`); } } } else if (item.id.includes('linkage')) { //console.log('Détails de la liaison :'); for (const key in item) { if (item.hasOwnProperty(key)) { //console.log(` ${key}: ${item[key]}`); } } } else { //console.log('Type de ligne inconnu :', item.id); } // Afficher les détails de chaque sous-tableau JSON /*if (item.standardRow) { console.log('Détails de la ligne standard :', item.standardRow); } if (item.estimationRow) { console.log('Détails de la ligne d\'estimation :', item.estimationRow); } if (item.specialRow) { console.log('Détails de la ligne spéciale :', item.specialRow); }*/ }); //console.log("<--------------- FIN file.json --------------------->"); preparation(data.data); } else if (data.status === 'error') { console.error('Erreur :', data.message); showMessageModal(data.message); } else { console.error('Réponse inattendue :', data); showMessageModal('Réponse inattendue du serveur.'); } }) .catch(error => { console.error('Erreur :', error); showMessageModal('Une erreur est survenue lors de la récupération des données.'); }); } function showMessageModal(message) { const modal = new bootstrap.Modal(document.getElementById('messageModal')); const modalBody = document.getElementById('messageModalBody'); modalBody.textContent = message; modal.show(); } function preparation(data) { regeneration(data); //display_import(data); } function display_import(data) { // Parcourir chaque élément (sous-tableau JSON) de data data.forEach((item, index) => { console.log(`Élément ${index + 1} :`); // Vérifier si l'id contient 'standard', 'estimation' ou 'special' if (item.id.includes('standard')) { console.log('Import : détails de la ligne standard :'); for (const key in item) { if (item.hasOwnProperty(key)) { if (key === 'cells' && Array.isArray(item[key])) { console.log(` ${key}:`); // pas utile de voir le détail de chaque cellule /*item[key].forEach((cell, cellIndex) => { console.log(` Cell ${cellIndex + 1}:`); for (const cellKey in cell) { if (cell.hasOwnProperty(cellKey)) { console.log(` ${cellKey}: ${cell[cellKey]}`); } } });*/ } else { console.log(` ${key}: ${item[key]}`); } } } } else if (item.id.includes('estimation')) { console.log('Import : Détails de la ligne d\'estimation :'); for (const key in item) { if (item.hasOwnProperty(key)) { console.log(` ${key}: ${item[key]}`); } } } else if (item.id.includes('special')) { console.log('Import : Détails de la ligne spéciale :'); for (const key in item) { if (item.hasOwnProperty(key)) { console.log(` ${key}: ${item[key]}`); } } } else if (item.id.includes('linkage')) { console.log('Détails de la liaison :'); for (const key in item) { if (item.hasOwnProperty(key)) { console.log(` ${key}: ${item[key]}`); } } } else { console.log('Type de ligne inconnu :', item.id); } }); } function code_annexe(data) { /* console.log(" ********** Début recherche ******************** "); // Afficher le contenu détaillé des objets //console.log("Contenu de standardRowsData :"); standardRowsData.forEach((row, index) => { console.log(`Ligne standard ${index + 1} :`, row); }); //console.log("Contenu de estimationRowsData :"); estimationRowsData.forEach((row, index) => { console.log(`Ligne d'estimation ${index + 1} :`, row); }); //console.log("Contenu de specialRowsData :"); specialRowsData.forEach((row, index) => { console.log(`Ligne spéciale ${index + 1} :`, row); }); //console.log("Contenu de linkages :"); linkages.forEach((linkage, index) => { console.log(`Liaison ${index + 1} :`, linkage); }); console.log(" ********** Fin recherche ******************** "); console.log(" ********** Début vérification purge ******************** "); standardRowsData.length = 0; estimationRowsData.length = 0; specialRowsData.length = 0; linkages.length = 0; if (standardRowsData.length === 0) { console.log(" standardRowsData empty"); } if (estimationRowsData.length === 0) { console.log(" estimationRowsData empty"); } if (specialRowsData.length === 0) { console.log(" specialRowsData empty"); } if (linkages.length === 0) { console.log(" linkages empty"); } console.log(" ********** Fin vérification purge ******************** "); */ // Afficher le nombre de sous-tableaux dans data //console.log("Nombre de sous-tableaux dans data :", data.length); /*for (const item of data) { if (item.id.includes('special')) { const specialRowData = { id: item.id, name: item.name }; specialRowsData.push(specialRowData); } }*/ /*for (let i = 0; i < data.length; i++) { console.log(" Indice " + i); }*/ } function regeneration(data) { console.log("Purging table and regenerating rows..."); // Clear existing table data tableBody.innerHTML = ""; standardRowsData.length = 0; estimationRowsData.length = 0; specialRowsData.length = 0; linkages.length = 0; data.forEach(item => { if (item.id.includes('linkage')) { console.log("Creating a linkage..."); const linkage = { id: item.id, standardRowId: item.standardRowId, estimationRowId: item.estimationRowId, }; linkages.push(linkage); } if (item.id.includes('standard')) { console.log("Creating a standard row..."); const standardRowData = { id: item.id, name: item.name, selectValue: item.selectValue, count: item.count, cells: item.cells, selection: item.selection // TAG : SELECTION }; standardRowsData.push(standardRowData); const standardRow = document.createElement("tr"); standardRow.setAttribute("draggable", "true"); standardRow.dataset.rowId = item.id; standardRow.title = standardRow.dataset.rowId; // Ajoutez cette ligne const firstCells = [item.name, "", item.count]; firstCells.forEach((text, index) => { const td = document.createElement("td"); td.dataset.cellId = `cell-${item.id}-${index}`; if (index === 0) { const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = item.name; input.addEventListener("click", function (event) { event.stopPropagation(); input.focus(); input.style.width = "130px"; console.log("Input clicked, setting width to 130px"); }); input.addEventListener("blur", function () { if (!keydownHandled && !alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } keydownHandled = false; alertShown = false; }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { keydownHandled = true; if (!alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } } }); td.appendChild(input); } else if (index === 1) { const select = document.createElement("select"); for (let i = 1; i <= 10; i++) { const option = document.createElement("option"); option.value = i; option.textContent = `Option ${i}`; select.appendChild(option); } select.value = item.selectValue; select.addEventListener("change", function () { updateRowData(select); }); td.appendChild(select); } else { td.textContent = text; } if (index === 0) { td.classList.add("row-header"); td.addEventListener("click", function (event) { event.preventDefault(); handleRowClick(standardRow, td); // TAG : SELECTION }); td.addEventListener("contextmenu", function (event) { event.preventDefault(); showContextMenu(event, standardRow); }); } standardRow.appendChild(td); }); const headerCells = document.querySelectorAll("thead tr:nth-child(2) th:not(.weekend):not(.holiday)"); const workingDaysCount = headerCells.length; for (let i = 0; i < workingDaysCount - 3; i++) { const td = document.createElement("td"); td.dataset.cellId = `cell-${item.id}-${i}`; td.dataset.cellValue = item.cells[i].value; td.dataset.cellColor = item.cells[i].color; td.textContent = item.cells[i].value; td.style.backgroundColor = item.cells[i].color; td.addEventListener("click", function () { const newValue = td.dataset.cellValue === "0" ? "1" : "0"; td.dataset.cellValue = newValue; td.textContent = newValue; td.style.backgroundColor = newValue === "1" ? "green" : "white"; td.dataset.cellColor = newValue === "1" ? "green" : "white"; updateCountCell(standardRow); updateRowData(td); }); td.addEventListener("contextmenu", function (event) { event.preventDefault(); if (td.dataset.cellValue === "1") { showColorContextMenu(event, td); } }); td.title = `ID: ${td.dataset.cellId}`; standardRow.appendChild(td); } if (item.selection === "ON") { standardRow.cells[0].style.backgroundColor = "red"; } tableBody.appendChild(standardRow); standardRow.addEventListener("dragstart", dragStart); standardRow.addEventListener("dragover", dragOver); standardRow.addEventListener("drop", drop); } if (item.id.includes('estimation')) { console.log("Creating an estimation row..."); const estimationRowData = { id: item.id, name: item.name, selectValue: item.selectValue, estimationValue: item.estimationValue, selection: item.selection // TAG : SELECTION }; estimationRowsData.push(estimationRowData); const estimationRow = document.createElement("tr"); estimationRow.setAttribute("draggable", "true"); estimationRow.dataset.rowId = item.id; estimationRow.classList.add("estimation-row"); estimationRow.title = estimationRow.dataset.rowId; // Ajoutez cette ligne const estimationFirstCells = [item.name, "", item.estimationValue]; estimationFirstCells.forEach((text, index) => { const td = document.createElement("td"); td.dataset.cellId = `cell-${item.id}-${index}`; if (index === 0) { const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = item.name; input.addEventListener("click", function (event) { event.stopPropagation(); input.focus(); input.style.width = "130px"; console.log("Input clicked, setting width to 130px"); }); input.addEventListener("blur", function () { if (!keydownHandled && !alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } keydownHandled = false; alertShown = false; }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { keydownHandled = true; if (!alertShown) { alertShown = true; input.classList.remove("editing"); input.blur(); input.style.width = "65px"; console.clear; updateRowData(input); } } }); td.appendChild(input); } else if (index === 1) { const select = document.createElement("select"); for (let i = 1; i <= 10; i++) { const option = document.createElement("option"); option.value = i; option.textContent = `Option ${i}`; select.appendChild(option); } select.value = item.selectValue; select.addEventListener("change", function () { updateRowData(select); }); td.appendChild(select); } else { const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = text; input.addEventListener("blur", function () { const value = parseInt(input.value, 10); if (isNaN(value) || value < 1 || value > 365) { input.value = "1"; showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365."); } else { updateRowData(input); } input.classList.remove("editing"); input.style.width = "65px"; }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { const value = parseInt(input.value, 10); if (isNaN(value) || value < 1 || value > 365) { input.value = "1"; showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365."); } else { updateRowData(input); } input.classList.remove("editing"); input.blur(); input.style.width = "65px"; } }); td.appendChild(input); } if (index === 0) { td.classList.add("row-header"); td.addEventListener("click", function (event) { event.preventDefault(); handleRowClick(estimationRow, td); // TAG : SELECTION }); td.addEventListener("contextmenu", function (event) { event.preventDefault(); showContextMenu(event, estimationRow); }); } estimationRow.appendChild(td); }); const mergedCell = document.createElement("td"); mergedCell.colSpan = document.querySelector("thead tr:nth-child(2)").cells.length - 3; mergedCell.textContent = ""; mergedCell.classList.add("no-click"); estimationRow.appendChild(mergedCell); if (item.selection === "ON") { estimationRow.cells[0].style.backgroundColor = "red"; } tableBody.appendChild(estimationRow); estimationRow.addEventListener("dragstart", dragStart); estimationRow.addEventListener("dragover", dragOver); estimationRow.addEventListener("drop", drop); } if (item.id.includes('special')) { console.log("Creating a special row..."); const specialRowData = { id: item.id, name: item.name }; specialRowsData.push(specialRowData); const specialRow = document.createElement("tr"); specialRow.classList.add("special-row"); specialRow.setAttribute("draggable", "true"); specialRow.dataset.rowId = item.id; specialRow.title = specialRow.dataset.rowId; // Ajoutez cette ligne const firstCell = document.createElement("td"); firstCell.classList.add("row-header"); const input = document.createElement("input"); input.type = "text"; input.classList.add("editable-input"); input.value = item.name; input.addEventListener("click", function (event) { event.stopPropagation(); input.focus(); input.style.width = "130px"; console.log("Input clicked, setting width to 130px"); }); input.addEventListener("blur", function () { input.classList.remove("editing"); input.style.width = "65px"; updateRowData(input); }); input.addEventListener("keydown", function (event) { if (event.key === "Escape" || event.key === "Enter") { input.classList.remove("editing"); input.blur(); input.style.width = "65px"; updateRowData(input); } }); input.addEventListener("input", function () { updateRowData(input); }); const addButton = document.createElement("button"); addButton.classList.add("add-button"); addButton.textContent = "+"; addButton.addEventListener("click", function () { toggleCollapse(specialRow); }); firstCell.appendChild(input); firstCell.appendChild(addButton); firstCell.addEventListener("contextmenu", function (event) { event.preventDefault(); showSpecialContextMenu(event, specialRow); }); specialRow.appendChild(firstCell); const mergedCell = document.createElement("td"); mergedCell.colSpan = 2; mergedCell.textContent = ""; specialRow.appendChild(mergedCell); const td = document.createElement("td"); td.textContent = `${item.name} - Détails`; td.colSpan = document.querySelector("thead tr:nth-child(2)").cells.length - 3; specialRow.appendChild(td); tableBody.appendChild(specialRow); specialRow.addEventListener("dragstart", dragStart); specialRow.addEventListener("dragover", dragOver); specialRow.addEventListener("drop", drop); } }); // Afficher les liaisons dans la console displayLinkages(); } document.getElementById("logButton").addEventListener("click", function () { const tableData = traceTable(); displayJSONData(tableData); }); function displayJSONData(data) { const jsonOutputElement = document.getElementById("jsonOutput"); const jsonOutput = JSON.stringify(data, null, 2); jsonOutputElement.textContent = jsonOutput; } document.getElementById("queryButton").addEventListener("click", function () { query(); }); }); </script> </body> </html>