File "tmp0019.php"

Full Path: /home/analogde/www/Dev tableau/tmp0019.php
File size: 24.5 KB
MIME-type: text/x-php
Charset: utf-8

<?php
/*
function getWorkingDays($startDate, $endDate, $holidays = []) {
    $start = strtotime($startDate);
    $end = strtotime($endDate);
    $workingDays = [];

    // Définir le locale en français
    setlocale(LC_TIME, 'fr_FR.UTF-8');

    // Générer toutes les dates entre startDate et endDate
    for ($currentDate = $start; $currentDate <= $end; $currentDate = strtotime("+1 day", $currentDate)) {
        $dayOfWeek = date("N", $currentDate); // Numéro du jour de la semaine (1 = lundi, 7 = dimanche)

        // Vérifier si ce jour est un week-end ou un jour férié
        if ($dayOfWeek < 6 && !in_array(date("Y-m-d", $currentDate), $holidays)) {
            $day = date("d", $currentDate); // Numéro du jour du mois
            $dayOfWeekName = strftime("%A", $currentDate); // Nom complet du jour en français
            $dayOfWeekInitial = strtoupper($dayOfWeekName[0]); // Initial du jour en français (première lettre)
            $weekNumber = date("W", $currentDate); // Numéro de la semaine

            // Ajouter un tableau avec ces trois informations dans $workingDays
            $workingDays[] = [
                'day' => $day,
                'day_of_week_initial' => $dayOfWeekInitial,
                'week_number' => $weekNumber
            ];
        }
    }

    return $workingDays;
}
*/

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;
}

// Liste des jours fériés et fêtes religieuses à exclure (exemple pour la France, à compléter avec d'autres fêtes)
$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%;
            max-height: 400px;
            overflow: auto;
            border: 1px solid #ccc;
            position: relative;
        }

        table {
            border-collapse: collapse;
            width: max-content;
            table-layout: fixed;
        }

        th, td {
            padding: 10px;
            text-align: center;
            height: 40px;
            border: 1px solid #ccc;
            white-space: nowrap;
            min-width: 120px;
            position: relative;
            background-color: white;
            box-sizing: border-box;
        }

        /* ✅ Fixation des cellules d'en-tête */
        th {
            background-color: #f2f2f2;
            position: sticky;
            top: 0;
            z-index: 100; /* Hauteur élevée pour éviter les chevauchements */
        }

        /* ✅ Colonnes sticky */
        th:first-child, td:first-child {
            position: sticky;
            left: 0;
            z-index: 101; /* Priorité plus haute */
            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;
        }

        /* ✅ Bordures droites persistantes */
        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;
        }

        /* ✅ Alternance des couleurs */
        tbody tr:nth-child(odd) {
            background-color: #f9f9f9;
        }

        /* ✅ Largeur fixe des autres colonnes */
        th:nth-child(n+4), td:nth-child(n+4) {
            /*min-width: 150px;*/

            min-width: 40px;
    max-width: 40px;
    width: 40px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

        }

        /* ✅ Deuxième ligne d'en-tête sticky */
        .second-header th {
            background-color: #f2f2f2;
            position: sticky;
            top: 40px;
            z-index: 99;
        }

        /* ✅ Troisième ligne d'en-tête sticky */
        .third-header th {
            background-color: #f2f2f2;
            position: sticky;
            top: 80px;
            z-index: 98;
        }

        /* ✅ Correction du positionnement des 3 premières colonnes de la deuxième et troisième ligne */
        .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;
        }

        /* ✅ Réajustement des z-index pour garantir l'ordre correct */
        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;
        }

        /* ✅ Bordures inférieures fixes sans chevauchement */
        thead tr:first-child th,
        .second-header th,
        .third-header th {
            box-shadow: inset 0 -2px #aaa;
            background-clip: padding-box;
            padding-bottom: 2px; /* Réduction du chevauchement */
            margin-bottom: -2px; /* Évite que les bordures ne recouvrent les autres cellules */
            z-index: 100; /* Priorité élevée */
        }

        /* Ajout d'un petit espace entre les lignes sticky pour éviter le chevauchement */
        .second-header th {
            top: calc(40px + 2px); /* Décale légèrement les lignes sticky vers le bas */
            margin-top: 2px; /* Donne un petit espace entre les lignes */
        }

        .third-header th {
            top: calc(80px + 2px); /* Décale la troisième ligne un peu plus bas */
            margin-top: 2px; /* Donne un petit espace entre les lignes */
        }

        /* ✅ Couleurs de fond pour les semaines paires et impaires */
        .even-week {
            background-color: #ffcc99 !important; /* Orange */
        }

        .odd-week {
            background-color: #e6b3ff !important; /* Violet */
        }


        /* ✅ Quatrième ligne d'en-tête sticky */
.fourth-header th {
    background-color: #f2f2f2;
    position: sticky;
    top: 120px;
    z-index: 97;
}

/* ✅ Correction du positionnement des 3 premières colonnes de la quatrième ligne */
.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;
}

/* ✅ Ajustement des z-index pour garantir un affichage correct */
.fourth-header th:first-child,
.fourth-header th:nth-child(2),
.fourth-header th:nth-child(3) {
    z-index: 102;
}

/* ✅ Ajout d'un espace entre les lignes sticky pour éviter le chevauchement */
.fourth-header th {
    top: calc(120px + 2px); /* Décalage pour éviter le chevauchement */
    margin-top: 2px;
}

/* ✅ Bordure inférieure pour séparer visuellement la ligne */
.fourth-header th {
    box-shadow: inset 0 -2px #aaa;
    background-clip: padding-box;
    padding-bottom: 2px;
    margin-bottom: -2px;
    z-index: 97;
}

.even-week {
    background-color: #ffcc99 !important; /* Orange */
}

.odd-week {
    background-color: #e6b3ff !important; /* Violet */
}

.month-even {
    background-color: #99ccff !important; /* Bleu clair */
}

.month-odd {
    background-color: #ff9999 !important; /* Rouge clair */
}


#addRowButton {
    margin-bottom: 20px;
    padding: 10px;
    background-color: #4CAF50;
    color: white;
    border: none;
    cursor: pointer;
    font-size: 16px;
}

#addRowButton:hover {
    background-color: #45a049;
}

#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;
}


    </style>



</head>
<body>

<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'];
            // Alterne les couleurs selon que le numéro de semaine est pair ou impair
            $weekClass = ($currentWeek % 2 === 0) ? 'even-week' : 'odd-week';
        }
        ?>
        <th class="<?= $weekClass; ?>"><?php echo $dateData['day_of_week_initial']; ?></th>
    <?php endforeach; ?>
</tr>


            <!-- ✅ Troisième ligne d'en-tête sticky avec fusion des cellules et couleurs de fond -->
            <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>

<!-- ✅ Quatrième ligne d'en-tête sticky -->

<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']; // Classes CSS pour alterner les couleurs

    foreach ($workingDays as $index => $dateData):
        $monthYear = ucfirst(strftime("%B %Y", strtotime($dateData['full_date'])));

        if ($currentMonthYear !== $monthYear) {
            if ($currentMonthYear !== null) {
                // Appliquer la couleur de fond en alternance
                echo '<th class="' . $monthClass . '" colspan="' . $colspan . '">' . $currentMonthYear . '</th>';
            }
            // Mise à jour des variables pour le nouveau mois
            $currentMonthYear = $monthYear;
            $colspan = 1;
            $monthClass = $colors[$colorIndex % 2]; // Alterne les couleurs
            $colorIndex++;
        } else {
            $colspan++;
        }
    endforeach;

    // Affichage de la dernière cellule fusionnée
    if ($currentMonthYear !== null) {
        echo '<th class="' . $monthClass . '" colspan="' . $colspan . '">' . $currentMonthYear . '</th>';
    }
    ?>
</tr>



        </thead>

        <tbody>
         
        </tbody>
    </table>
</div>


<button id="addRowButton">Ajouter une ligne</button>

<!-- -->

<script>
    /*
// Fonction pour ajouter une nouvelle ligne
function addRow() {
    const table = document.querySelector("table");
    const tableBody = table.querySelector("tbody");

    // Calculer le numéro de la ligne suivante
    const rowNumber = tableBody.rows.length + 1;
    
    // Créer la nouvelle ligne
    const newRow = document.createElement("tr");

    // Ajouter les 3 premières cellules
    newRow.innerHTML = `
        <td>Row ${rowNumber}</td>
        <td>Data ${rowNumber}-2</td>
        <td>cretin ${rowNumber}</td>
    `;

    // Ajouter les autres cellules avec la valeur 0 (basé sur le nombre de dates)
    const workingDaysCells = document.querySelectorAll("thead th"); // Récupérer toutes les cellules d'entête
    const dateCellsCount = workingDaysCells.length - 3; // Exclure les 3 premières cellules

    for (let i = 0; i < dateCellsCount; i++) {
        const td = document.createElement("td");
        td.textContent = "0";  // Définir la valeur de la cellule sur 0
        newRow.appendChild(td);
    }

    // Ajouter la nouvelle ligne au body du tableau
    tableBody.appendChild(newRow);
}*/
/*
function addRow() {
    const table = document.querySelector("table");
    const tableBody = table.querySelector("tbody");

    // Calculer le numéro de la ligne suivante
    const rowNumber = tableBody.rows.length + 1;

    // Créer la nouvelle ligne
    const newRow = document.createElement("tr");

    // Ajouter les 3 premières cellules
    newRow.innerHTML = `
        <td>Row ${rowNumber}</td>
        <td>Data ${rowNumber}-2</td>
        <td>cretin ${rowNumber}</td>
    `;

    // Sélectionner uniquement les cellules des jours ouvrés depuis l'en-tête
    const workingDaysCells = document.querySelectorAll("thead tr:nth-child(2) th:not(.weekend):not(.holiday)");
    const dateCellsCount = workingDaysCells.length; // Nombre exact de colonnes des jours ouvrés

    // Ajouter les cellules des jours ouvrés avec la valeur 0
    for (let i = 0; i < dateCellsCount; i++) {
        const td = document.createElement("td");
        td.textContent = "0"; // Définir la valeur de la cellule sur 0
        newRow.appendChild(td);
    }

    // Ajouter la nouvelle ligne au body du tableau
    tableBody.appendChild(newRow);
}
*/
/*
function addRow() {
    const table = document.querySelector("table");
    const tableBody = table.querySelector("tbody");

    // Calculer le numéro de la ligne suivante
    const rowNumber = tableBody.rows.length + 1;

    // Créer la nouvelle ligne
    const newRow = document.createElement("tr");

    // Ajouter les 3 premières cellules
    newRow.innerHTML = `
        <td>Row ${rowNumber}</td>
        <td>Data ${rowNumber}-2</td>
        <td>cretin ${rowNumber}</td>
    `;

    // Sélectionner uniquement les cellules des jours ouvrés depuis l'en-tête
    const workingDaysCells = document.querySelectorAll("thead tr:nth-child(2) th:not(.weekend):not(.holiday)");
    
    // Nombre de jours ouvrés (sans compter les 3 premières colonnes)
    const dateCellsCount = workingDaysCells.length;

    // Ajouter les cellules des jours ouvrés avec la valeur 0
    for (let i = 0; i < dateCellsCount; i++) {
        const td = document.createElement("td");
        td.textContent = "0"; // Définir la valeur de la cellule sur 0
        newRow.appendChild(td);
    }

    // Ajouter la nouvelle ligne au body du tableau
    tableBody.appendChild(newRow);
}*/

// Fonction pour ajouter une nouvelle ligne standard
/*function addRow() {
    const table = document.querySelector("table");
    const tableBody = table.querySelector("tbody");

    // Calculer le numéro de la ligne suivante
    const rowNumber = tableBody.rows.length + 1;

    // Créer la nouvelle ligne
    const newRow = document.createElement("tr");

    // Ajouter les 3 premières cellules
    newRow.innerHTML = `
        <td>Row ${rowNumber}</td>
        <td>Data ${rowNumber}-2</td>
        <td>cretin ${rowNumber}</td>
    `;

    // Récupérer uniquement les jours ouvrés (exclure weekends et jours fériés)
    const workingDaysCells = document.querySelectorAll("thead tr:nth-child(2) th:not(.weekend):not(.holiday)");
    
    // Nombre de jours ouvrés (à partir de la colonne 4)
    const decompte = workingDaysCells.length;

    console.log(" --- " + decompte);

// Récupérer uniquement les jours affichés dans l'en-tête
const headerCells = document.querySelectorAll("thead tr:nth-child(2) th:not(.weekend):not(.holiday)");
    const workingDaysCount = headerCells.length; // Nombre exact de jours ouvrés

    console.log("Nombre de colonnes affichées (hors weekends et jours fériés) :", workingDaysCount);



    
    // Ajouter uniquement les colonnes correspondant aux jours ouvrés
    for (let i = 0; i < workingDaysCount - 3; i++) {
        const td = document.createElement("td");
        td.textContent = "0"; // Valeur par défaut
        newRow.appendChild(td);
    }

// Vérifier le nombre total de cellules ajoutées
console.log("Nombre total de cellules dans la nouvelle ligne :", newRow.cells.length);

    // Ajouter la nouvelle ligne au body du tableau
    tableBody.appendChild(newRow);
}
*/

/*
function addRow() {
    const table = document.querySelector("table");
    const tableBody = table.querySelector("tbody");

    // Numéro de la nouvelle ligne
    const rowNumber = tableBody.rows.length + 1;

    // Créer une nouvelle ligne
    const newRow = document.createElement("tr");

    // Ajouter les 3 premières cellules avec du texte spécifique
    const firstCells = ["Row " + rowNumber, "Data " + rowNumber + "-2", "cretin " + rowNumber];
    firstCells.forEach(text => {
        const td = document.createElement("td");
        td.textContent = text;
        newRow.appendChild(td);
    });

    // Récupérer uniquement les jours affichés dans l'en-tête
    const headerCells = document.querySelectorAll("thead tr:nth-child(2) th:not(.weekend):not(.holiday)");
    const workingDaysCount = headerCells.length; // Nombre exact de jours ouvrés

    // Ajouter les cellules interactives
    for (let i = 0; i < workingDaysCount; i++) {
        const td = document.createElement("td");
        td.textContent = "0"; // Valeur initiale
        td.style.backgroundColor = "white"; // Fond blanc par défaut

        // Ajouter l'événement de clic pour basculer entre 0 et 1
        td.addEventListener("click", function () {
            if (td.textContent === "0") {
                td.textContent = "1";
                td.style.backgroundColor = "green";
            } else {
                td.textContent = "0";
                td.style.backgroundColor = "white";
            }
        });

        newRow.appendChild(td);
    }

    // Ajouter la nouvelle ligne au tableau
    tableBody.appendChild(newRow);
}
*/

document.addEventListener("DOMContentLoaded", function () {
    const tableBody = document.querySelector("tbody");

    // Création du menu contextuel
    const contextMenu = document.createElement("div");
    contextMenu.id = "contextMenu";
    contextMenu.classList.add("dropdown-menu");
    contextMenu.style.display = "none";
    document.body.appendChild(contextMenu);

    function addRow() {
        const rowNumber = tableBody.rows.length + 1;
        const newRow = document.createElement("tr");

        // Ajout des 3 premières cellules
        const firstCells = ["Row " + rowNumber, "Data " + rowNumber + "-2", "cretin " + rowNumber];
        firstCells.forEach((text, index) => {
            const td = document.createElement("td");
            td.textContent = text;

            if (index === 0) {
                td.classList.add("row-header");
                td.addEventListener("contextmenu", function (event) {
                    event.preventDefault();
                    showContextMenu(event, newRow);
                });
            }

            newRow.appendChild(td);
        });

        // Récupération des jours actifs
        const headerCells = document.querySelectorAll("thead tr:nth-child(2) th:not(.weekend):not(.holiday)");
        const workingDaysCount = headerCells.length;

        for (let i = 0; i < workingDaysCount; i++) {
            const td = document.createElement("td");
            td.textContent = "0";
            td.style.backgroundColor = "white";

            td.addEventListener("click", function () {
                td.textContent = td.textContent === "0" ? "1" : "0";
                td.style.backgroundColor = td.textContent === "1" ? "green" : "white";
            });

            newRow.appendChild(td);
        }

        tableBody.appendChild(newRow);
    }

    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>
        `;

        contextMenu.style.top = `${event.clientY}px`;
        contextMenu.style.left = `${event.clientX}px`;
        contextMenu.style.display = "flex"; // Affichage en colonne
        contextMenu.style.flexDirection = "column";

        document.getElementById("add-row").addEventListener("click", function () {
            addRow();
            hideContextMenu();
        });

        document.getElementById("delete-row").addEventListener("click", function () {
            row.remove();
            hideContextMenu();
        });
    }

    document.addEventListener("click", function (event) {
        if (!contextMenu.contains(event.target)) {
            hideContextMenu();
        }
    });

    function hideContextMenu() {
        contextMenu.style.display = "none";
    }

    document.getElementById("addRowButton").addEventListener("click", addRow);

    document.querySelectorAll("tbody tr td:first-child").forEach(td => {
        td.addEventListener("contextmenu", function (event) {
            event.preventDefault();
            showContextMenu(event, td.parentElement);
        });
    });
});


//document.getElementById("addRowButton").addEventListener("click", addRow);

</script>

<!-- -->

</body>
</html>