File "stable016.html"

Full Path: /home/analogde/www/Design/Dev tableau/stable016.html
File size: 27.89 KB
MIME-type: text/html
Charset: utf-8

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tableau Dynamique</title>
    <style>
        table {
            width: auto;
            min-width: 1200px;
            border-collapse: separate;
            border-spacing: 0;
        }
        th, td {
            border: 1px solid black;
            padding: 8px;
            text-align: center;
            white-space: nowrap;
            box-sizing: border-box;
        }
        thead th {
            background: #f8f8f8;
            position: sticky;
            top: 0;
            z-index: 2;
        }
        .table-container {
            width: 100%;
            overflow-x: auto;
            position: relative;
            margin-top: 20px;
            border: 1px solid #ddd;
        }
        th:nth-child(n+1):nth-child(-n+3), td:nth-child(n+1):nth-child(-n+3) {
            position: sticky;
            z-index: 4;
            background: white;
            border-right: 2px solid black;
        }
        th:nth-child(1), td:nth-child(1) {
            left: 0;
            width: 210px;
            min-width: 210px;
            max-width: 210px;
        }
        th:nth-child(2), td:nth-child(2) {
            left: 210px;
            width: 80px;
            min-width: 80px;
            max-width: 80px;
        }
        th:nth-child(3), td:nth-child(3) {
            left: 290px;
            width: 100px;
            min-width: 100px;
            max-width: 100px;
        }
        td:first-child {
            display: flex;
            justify-content: center;
            align-items: center;
        }
        select {
            width: 100%;
            max-width: 80px;
        }
        input[type="text"] {
            width: calc(100% - 20px);
            box-sizing: border-box;
        }
        button {
            margin-top: 20px;
            padding: 10px;
            font-size: 16px;
        }
        .cell-active {
            background-color: green;
        }
        th:nth-child(n+4), td:nth-child(n+4) {
            width: 50px;
            min-width: 50px;
            max-width: 50px;
        }
        .unused-cell {
            background-color: #cccccc;
        }
        .dragging {
            opacity: 0.5;
        }
        .collapse-cell {
            background-color: orange;
        }
        .special-cell {
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: relative;
            padding: 0;
        }
        .special-cell input {
            width: calc(100% - 30px);
            margin-right: 10px;
            height: 20px;
        }
        .special-cell button {
            width: 20px;
            height: 20px;
            background-color: orange;
            border: none;
            cursor: pointer;
            display: flex;
            justify-content: center;
            align-items: center;
            margin: 0;
        }
        .context-menu {
            display: none;
            position: absolute;
            background-color: white;
            border: 1px solid #ccc;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            z-index: 1000;
        }
        .context-menu ul {
            list-style: none;
            padding: 0;
            margin: 0;
        }
        .context-menu ul li {
            padding: 8px 12px;
            cursor: pointer;
            display: flex;
            align-items: center;
        }
        .context-menu ul li:hover {
            background-color: #f0f0f0;
        }
        .context-menu ul li .color-box {
            width: 15px;
            height: 15px;
            margin-right: 10px;
        }
    </style>
</head>
<body>
<div class="table-container">
    <table>
        <thead>
            <tr id="header-row">
                <th>plouf</th>
                <th>Nom</th>
                <th>Total</th>
            </tr>
            <tr id="month-row">
                <th class="unused-cell">Non utilisé</th>
                <th>Mois</th>
                <th class="unused-cell">Non utilisé</th>
            </tr>
            <tr id="day-row">
                <th class="unused-cell">Non utilisé</th>
                <th>Jours</th>
                <th class="unused-cell">Non utilisé</th>
            </tr>
            <tr id="numero-row">
                <th class="unused-cell">Non utilisé</th>
                <th>Semaine</th>
                <th class="unused-cell">Non utilisé</th>
            </tr>
        </thead>
        <tbody id="table-body"></tbody>
    </table>
</div>
<button id="getDataButton">Récupérer les données du tableau</button>
<button id="sendDataButton">Envoyer les données</button>
<button id="readDataButton">Lire les données</button>
<button id="addRowButton">Ajouter une ligne</button>
<button id="addSpecialRowButton">Ajouter une ligne spéciale</button>

<div id="contextMenu" class="context-menu">
    <ul>
        <li id="deleteRow">Supprimer</li>
        <li id="addRowContext">Ajouter une ligne</li>
        <li id="changeColorRed">Changer la couleur en rouge</li>
        <li id="changeColorGreen">Changer la couleur en vert</li>
        <li id="changeColorBlue">Changer la couleur en bleu</li>
        <li id="changeColorNone">Pas de couleur</li>
    </ul>
</div>

<div id="specialRowContextMenu" class="context-menu">
    <ul>
        <li id="deleteSpecialRow">Supprimer</li>
        <li id="addRowAfterSpecial">Ajouter une ligne</li>
    </ul>
</div>

<div id="cellContextMenu" class="context-menu">
    <ul>
        <li id="cellColorRed"><span class="color-box" style="background-color: red;"></span> Rouge</li>
        <li id="cellColorGreen"><span class="color-box" style="background-color: green;"></span> Vert</li>
        <li id="cellColorBlue"><span class="color-box" style="background-color: blue;"></span> Bleu</li>
        <li id="cellColorYellow"><span class="color-box" style="background-color: yellow;"></span> Jaune</li>
        <li id="cellColorPurple"><span class="color-box" style="background-color: purple;"></span> Violet</li>
    </ul>
</div>

<script>
    const numCols = 100;
    const holidays = [
        '2025-01-01',
        '2025-04-21',
        '2025-05-01',
        '2025-05-08',
        '2025-05-29',
        '2025-06-09',
        '2025-07-14',
        '2025-08-15',
    ];
    let targetRow = null;
    let targetCell = null;
    let currentContextRow = null;

    function createTable() {
        const theadRow = document.getElementById("header-row");
        const monthRow = document.getElementById("month-row");
        const dayRow = document.getElementById("day-row");
        const numeroWeekRow = document.getElementById("numero-row");
        let currentDate = new Date('2024-06-01');
        const endDate = new Date('2025-06-30');
        let lastMonth = "";
        let currentColor = "#E0E0E0";
        let weekNumber = getISOWeekNumber(currentDate);
        let lastThMonth = null;
        let colSpanMonth = 0;
        let lastWeekNumber = null;
        let weekTh = null;
        let colSpanWeek = 0;

        function getISOWeekNumber(date) {
            const dateCopy = new Date(date.getTime());
            dateCopy.setHours(0, 0, 0, 0);
            dateCopy.setDate(dateCopy.getDate() + 3 - (dateCopy.getDay() + 6) % 7);
            const firstThursday = new Date(dateCopy.getFullYear(), 0, 1);
            return Math.ceil(((dateCopy - firstThursday) / 86400000 + 1) / 7);
        }

        while (currentDate <= endDate) {
            const dayOfWeek = currentDate.getDay();
            const dateString = currentDate.toISOString().split('T')[0];

            if (dayOfWeek !== 0 && dayOfWeek !== 6 && !holidays.includes(dateString)) {
                let th = document.createElement("th");
                th.textContent = currentDate.getDate();
                theadRow.appendChild(th);

                let currentWeekNumber = getISOWeekNumber(currentDate);

                let monthShort = currentDate.toLocaleString('default', { month: 'long' });
                monthShort = monthShort.charAt(0).toUpperCase() + monthShort.slice(1);
                if (monthShort === lastMonth) {
                    colSpanMonth++;
                    lastThMonth.colSpan = colSpanMonth;
                } else {
                    lastMonth = monthShort;
                    colSpanMonth = 1;
                    lastThMonth = document.createElement("th");
                    lastThMonth.textContent = monthShort + " " + currentDate.getFullYear();
                    monthRow.appendChild(lastThMonth);

                    if (parseInt(currentDate.toLocaleString('default', { month: 'numeric' })) % 2 === 0) {
                        lastThMonth.style.backgroundColor = "#E0E0E0";
                    } else {
                        lastThMonth.style.backgroundColor = "#B0C4DE";
                    }
                }

                th.style.backgroundColor = (currentDate.getMonth() % 2 === 0) ? "#FFA500" : "#0000FF";

                let dayTh = document.createElement("th");
                dayTh.textContent = currentDate.toLocaleString('default', { weekday: 'short' }).charAt(0).toUpperCase();
                dayRow.appendChild(dayTh);

                if (dayOfWeek === 1) {
                    currentColor = (currentColor === "#E0E0E0") ? "#B0C4DE" : "#E0E0E0";
                    weekNumber = getISOWeekNumber(currentDate);
                }
                dayTh.style.backgroundColor = currentColor;

                if (currentWeekNumber === lastWeekNumber) {
                    colSpanWeek++;
                    weekTh.colSpan = colSpanWeek;
                } else {
                    weekTh = document.createElement("th");
                    weekTh.textContent = currentWeekNumber;
                    weekTh.colSpan = 1;
                    numeroWeekRow.appendChild(weekTh);

                    lastWeekNumber = currentWeekNumber;
                    colSpanWeek = 1;
                }
            }
            currentDate.setDate(currentDate.getDate() + 1);
        }
    }

    function addRow(event) {
        const tbody = document.getElementById("table-body");
        const headerRow = document.getElementById("header-row");
        const numDateCells = headerRow.querySelectorAll("th").length - 3;

        let row = document.createElement("tr");
        row.setAttribute('draggable', 'true');

        row.addEventListener('dragstart', handleDragStart);
        row.addEventListener('dragover', handleDragOver);
        row.addEventListener('drop', handleDrop);

        let inputCell = document.createElement("td");
        let input = document.createElement("input");
        input.type = "text";
        input.addEventListener('click', function(event) {
            event.stopPropagation();
            input.focus();
        });
        input.addEventListener('keydown', function(event) {
            if (event.key === 'Enter') {
                input.blur();
            }
        });
        inputCell.appendChild(input);
        inputCell.addEventListener('contextmenu', showContextMenu);
        row.appendChild(inputCell);

        let selectCell = document.createElement("td");
        let select = document.createElement("select");
        for (let j = 1; j <= 5; j++) {
            let option = document.createElement("option");
            option.textContent = j;
            select.appendChild(option);
        }
        selectCell.appendChild(select);
        row.appendChild(selectCell);

        let totalCell = document.createElement("td");
        totalCell.textContent = "0";
        row.appendChild(totalCell);

        let total = 0;
        for (let j = 0; j < numDateCells; j++) {
            let cell = document.createElement("td");
            let value = Math.random() < 0.5 ? "1" : "0";
            cell.textContent = value;
            if (value === "1") {
                cell.classList.add('cell-active');
            }
            total += parseInt(value);
            cell.addEventListener('click', handleCellClick);
            cell.addEventListener('contextmenu', showCellContextMenu);
            row.appendChild(cell);
        }

        totalCell.textContent = total;

        if (event) {
            const targetRow = event.target.closest('tr');
            if (targetRow) {
                targetRow.parentNode.insertBefore(row, targetRow.nextSibling);
            } else {
                tbody.appendChild(row);
            }
        } else {
            tbody.appendChild(row);
        }
    }

    function addSpecialRow() {
        const tbody = document.getElementById("table-body");
        let row = document.createElement("tr");
        row.classList.add('special-row');
        row.setAttribute('draggable', 'true');
        row.addEventListener('dragstart', handleDragStart);
        row.addEventListener('dragover', handleDragOver);
        row.addEventListener('drop', handleDrop);

        let specialCell = document.createElement("td");
        specialCell.classList.add('special-cell');

        let input = document.createElement("input");
        input.type = "text";
        input.addEventListener('click', function() {
            input.focus();
        });
        input.addEventListener('keydown', function(event) {
            if (event.key === 'Enter') {
                input.blur();
            }
        });
        specialCell.appendChild(input);

        let button = document.createElement("button");
        button.textContent = "+";
        button.addEventListener('click', function() {
            toggleCollapse(row);
        });
        specialCell.appendChild(button);

        specialCell.addEventListener('contextmenu', showContextMenu);

        row.appendChild(specialCell);

        tbody.appendChild(row);
    }

    function toggleCollapse(row) {
        const tbody = document.getElementById("table-body");
        const rows = Array.from(tbody.querySelectorAll('tr'));
        const index = rows.indexOf(row);
        const nextSpecialRowIndex = rows.findIndex((r, i) => i > index && r.classList.contains('special-row'));
        const isCollapsed = row.classList.toggle('collapsed');

        rows.forEach((r, i) => {
            if (i > index && (nextSpecialRowIndex === -1 || i < nextSpecialRowIndex)) {
                r.style.display = isCollapsed ? 'none' : '';
            }
        });

        row.querySelector('td').style.backgroundColor = isCollapsed ? 'orange' : 'white';
    }

    function handleDragStart(event) {
        event.dataTransfer.setData('text/plain', event.target.rowIndex);
        setTimeout(() => {
            event.target.classList.add('dragging');
        }, 0);
    }

    function handleDragOver(event) {
        event.preventDefault();
        const draggingRow = document.querySelector('.dragging');
        const targetRow = event.target.closest('tr');
        if (targetRow && draggingRow !== targetRow) {
            const tbody = document.getElementById("table-body");
            if (targetRow.rowIndex > draggingRow.rowIndex) {
                tbody.insertBefore(draggingRow, targetRow.nextSibling);
            } else {
                tbody.insertBefore(draggingRow, targetRow);
            }
        }
    }

    function handleDrop(event) {
        event.preventDefault();
        const draggingRow = document.querySelector('.dragging');
        if (draggingRow) {
            draggingRow.classList.remove('dragging');
        }
    }

    function handleCellClick(event) {
        const cell = event.target;
        const row = cell.parentElement;
        const totalCell = row.querySelector('td:nth-child(3)');
        let total = parseInt(totalCell.textContent);
        if (cell.textContent === "0") {
            cell.textContent = "1";
            cell.classList.add('cell-active');
            total += 1;
        } else {
            cell.textContent = "0";
            cell.classList.remove('cell-active');
            total -= 1;
        }
        totalCell.textContent = total;

        // Reset row background color if all cells are "0"
        const allCells = row.querySelectorAll('td:not(:nth-child(1)):not(:nth-child(2)):not(:nth-child(3))');
        const allZero = Array.from(allCells).every(cell => cell.textContent === "0");
        if (allZero) {
            row.style.backgroundColor = '';
        }
    }

    function showContextMenu(event) {
        event.preventDefault();
        const targetRow = event.target.closest('tr');
        const isSpecialRow = targetRow.classList.contains('special-row');
        const contextMenu = isSpecialRow ? document.getElementById('specialRowContextMenu') : document.getElementById('contextMenu');

        console.log(`Showing context menu for ${isSpecialRow ? 'special row' : 'standard row'}`);

        contextMenu.style.display = 'block';
        contextMenu.style.left = `${event.pageX}px`;
        contextMenu.style.top = `${event.pageY}px`;

        document.addEventListener('click', function hideContextMenu(event) {
            if (!contextMenu.contains(event.target)) {
                contextMenu.style.display = 'none';
                document.removeEventListener('click', hideContextMenu);
            }
        });

        // Store the target row for later use
        currentContextRow = targetRow;
    }

    function showCellContextMenu(event) {
        event.preventDefault();
        if (event.target.textContent === "1") {
            const cellContextMenu = document.getElementById('cellContextMenu');
            cellContextMenu.style.display = 'block';
            cellContextMenu.style.left = `${event.pageX}px`;
            cellContextMenu.style.top = `${event.pageY}px`;

            targetCell = event.target;

            document.addEventListener('click', function hideCellContextMenu(event) {
                if (!cellContextMenu.contains(event.target)) {
                    cellContextMenu.style.display = 'none';
                    document.removeEventListener('click', hideCellContextMenu);
                }
            });
        }
    }

    window.onload = function() {
        createTable();

        const addRowButton = document.getElementById('addRowButton');
        addRowButton.addEventListener('click', addRow);

        const addRowContextButton = document.getElementById('addRowContext');
        addRowContextButton.addEventListener('click', function() {
            addRow({ target: currentContextRow });
            contextMenu.style.display = 'none';
        });

        const deleteRowButton = document.getElementById('deleteRow');
        deleteRowButton.addEventListener('click', function() {
            if (currentContextRow) {
                currentContextRow.remove();
                contextMenu.style.display = 'none';
            }
        });

        const deleteSpecialRowButton = document.getElementById('deleteSpecialRow');
        deleteSpecialRowButton.addEventListener('click', function() {
            if (currentContextRow) {
                currentContextRow.remove();
                specialRowContextMenu.style.display = 'none';
            }
        });

        const addRowAfterSpecialButton = document.getElementById('addRowAfterSpecial');
        addRowAfterSpecialButton.addEventListener('click', function() {
            addRow({ target: currentContextRow });
            specialRowContextMenu.style.display = 'none';
        });

        const changeColorRedButton = document.getElementById('changeColorRed');
        changeColorRedButton.addEventListener('click', function() {
            if (currentContextRow) {
                currentContextRow.style.backgroundColor = 'red';
                contextMenu.style.display = 'none';
            }
        });

        const changeColorGreenButton = document.getElementById('changeColorGreen');
        changeColorGreenButton.addEventListener('click', function() {
            if (currentContextRow) {
                currentContextRow.style.backgroundColor = 'green';
                contextMenu.style.display = 'none';
            }
        });

        const changeColorBlueButton = document.getElementById('changeColorBlue');
        changeColorBlueButton.addEventListener('click', function() {
            if (currentContextRow) {
                currentContextRow.style.backgroundColor = 'blue';
                contextMenu.style.display = 'none';
            }
        });

        const changeColorNoneButton = document.getElementById('changeColorNone');
        changeColorNoneButton.addEventListener('click', function() {
            if (currentContextRow) {
                currentContextRow.style.backgroundColor = '';
                contextMenu.style.display = 'none';
            }
        });

        const cellColorRedButton = document.getElementById('cellColorRed');
        cellColorRedButton.addEventListener('click', function() {
            if (targetCell && targetCell.textContent === "1") {
                targetCell.style.backgroundColor = 'red';
                cellContextMenu.style.display = 'none';
            }
        });

        const cellColorGreenButton = document.getElementById('cellColorGreen');
        cellColorGreenButton.addEventListener('click', function() {
            if (targetCell && targetCell.textContent === "1") {
                targetCell.style.backgroundColor = 'green';
                cellContextMenu.style.display = 'none';
            }
        });

        const cellColorBlueButton = document.getElementById('cellColorBlue');
        cellColorBlueButton.addEventListener('click', function() {
            if (targetCell && targetCell.textContent === "1") {
                targetCell.style.backgroundColor = 'blue';
                cellContextMenu.style.display = 'none';
            }
        });

        const cellColorYellowButton = document.getElementById('cellColorYellow');
        cellColorYellowButton.addEventListener('click', function() {
            if (targetCell && targetCell.textContent === "1") {
                targetCell.style.backgroundColor = 'yellow';
                cellContextMenu.style.display = 'none';
            }
        });

        const cellColorPurpleButton = document.getElementById('cellColorPurple');
        cellColorPurpleButton.addEventListener('click', function() {
            if (targetCell && targetCell.textContent === "1") {
                targetCell.style.backgroundColor = 'purple';
                cellContextMenu.style.display = 'none';
            }
        });

        document.getElementById('getDataButton').addEventListener('click', logTableData);
        document.getElementById('sendDataButton').addEventListener('click', sendTableData);
        document.getElementById('readDataButton').addEventListener('click', readTableData);
        document.getElementById('addSpecialRowButton').addEventListener('click', addSpecialRow);
    };

    function getTableData() {
        let rows = document.querySelectorAll('tbody tr');
        let tableData = [];
        rows.forEach(function(row) {
            let rowData = [];
            let cells = row.querySelectorAll('td');
            cells.forEach(function(cell) {
                if (cell.querySelector('select')) {
                    rowData.push(cell.querySelector('select').value);
                } else if (cell.querySelector('input')) {
                    rowData.push(cell.querySelector('input').value);
                } else {
                    rowData.push(cell.innerText);
                }
            });
            tableData.push(rowData);
        });
        return tableData;
    }

    function logTableData() {
        let data = getTableData();
        console.log(data);
        console.log(JSON.stringify(data, null, 2));
    }

    function sendTableData() {
        let data = getTableData();
        let jsonData = JSON.stringify(data);
        fetch('insert.php', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: jsonData
        })
        .then(response => response.json())
        .then(data => {
            alert(data.message);
        })
        .catch(error => {
            console.error('Erreur:', error);
        });
    }

    function readTableData() {
        fetch('lecture.php', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            }
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                updateTable(data.data_json);
            } else {
                alert('Erreur lors de la récupération des données.');
            }
        })
        .catch(error => {
            console.error('Erreur:', error);
        });
    }

    function updateTable(data) {
        let tableData = JSON.parse(data);
        const tbody = document.getElementById("table-body");
        while (tbody.firstChild) {
            tbody.removeChild(tbody.firstChild);
        }
        tableData.forEach(rowData => {
            if (rowData.length === 1) {
                addSpecialRow();
                let specialRow = tbody.lastChild;
                specialRow.querySelector('input').value = rowData[0];
            } else {
                let row = document.createElement("tr");
                row.setAttribute('draggable', 'true');
                row.addEventListener('dragstart', handleDragStart);
                row.addEventListener('dragover', handleDragOver);
                row.addEventListener('drop', handleDrop);

                let inputCell = document.createElement("td");
                let input = document.createElement("input");
                input.type = "text";
                input.value = rowData[0];
                input.addEventListener('click', function(event) {
                    event.stopPropagation();
                    input.focus();
                });
                input.addEventListener('keydown', function(event) {
                    if (event.key === 'Enter') {
                        input.blur();
                    }
                });
                inputCell.appendChild(input);
                inputCell.addEventListener('contextmenu', showContextMenu);
                row.appendChild(inputCell);

                let selectCell = document.createElement("td");
                let select = document.createElement("select");
                for (let j = 1; j <= 5; j++) {
                    let option = document.createElement("option");
                    option.textContent = j;
                    select.appendChild(option);
                }
                select.value = rowData[1];
                selectCell.appendChild(select);
                row.appendChild(selectCell);

                let totalCell = document.createElement("td");
                row.appendChild(totalCell);

                let total = 0;
                for (let j = 3; j < rowData.length; j++) {
                    let cell = document.createElement("td");
                    cell.textContent = rowData[j];
                    if (rowData[j] === "1") {
                        cell.classList.add('cell-active');
                    }
                    total += parseInt(rowData[j]);
                    cell.addEventListener('click', handleCellClick);
                    cell.addEventListener('contextmenu', showCellContextMenu);
                    row.appendChild(cell);
                }

                totalCell.textContent = total;
                tbody.appendChild(row);
            }
        });
    }
</script>
</body>
</html>