File "table_004.php"
Full Path: /home/analogde/www/CURL/tmp/table_004.php
File size: 117.29 KB
MIME-type: text/x-php
Charset: utf-8
<?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">×</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">×</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">×</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">×</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="query" 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;
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) {
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";
} else if (standardRowData.selection === "ON" && estimationRowData.selection === "ON") {
standardRowData.selection = "OFF";
estimationRowData.selection = "OFF";
td.style.backgroundColor = "white";
linkedRow.cells[0].style.backgroundColor = "white";
}
}
}
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 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();
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);
}
}
});
td.appendChild(input);
}
if (index === 0) {
td.classList.add("row-header");
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);
// 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("click", function (event) {
event.stopPropagation();
input.focus();
input.style.width = "130px";
console.log("Input clicked, setting width to 130px");
});
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;
}
});
</script>
</body>
</html>