diff --git a/app/static/css/table_editor.css b/app/static/css/table_editor.css index 04faa9434..d3fe5a0f3 100644 --- a/app/static/css/table_editor.css +++ b/app/static/css/table_editor.css @@ -7,87 +7,53 @@ body { /***************************/ /* Le tableau */ /***************************/ -.tableau { +.tableau{ display: grid; grid-auto-rows: minmax(24px, auto); + gap: 2px; } - -.entete { +.entete{ background: #09c; font-weight: bold; } - -.tableau>div { - padding: 4px; +.tableau>div{ + padding: 4px 8px; + border-radius: 4px; border: 1px solid #999; grid-column: var(--x) / span var(--nbX); grid-row: var(--y) / span var(--nbY); } -/***************************/ -/* Attente */ -/***************************/ -.wait { - position: fixed; - top: 32px; - left: 50%; - height: 4px; - width: 32px; - margin-left: -16px; - background: #424242; - animation: attente 0.4s infinite alternate; - display: none; -} - -.go { - display: block; -} - -@keyframes attente { - 100% { - transform: translateY(-16px) rotate(360deg); - } -} - -/***************************/ -/* Système de modification */ -/***************************/ -.modifOnOff { - position: relative; - display: table; - margin: 16px; - padding-right: 8px; +[data-editable="true"]{ cursor: pointer; } -.modifOnOff::before { - content: ''; - width: 40px; - height: 20px; - background: #c90; - position: absolute; - top: 0; - left: 100%; - border-radius: 20px; - transition: 0.2s; -} +/***************************/ +/* Statut des cellules */ +/***************************/ +.selected{ outline: 1px solid #c09; } +.modifying{ outline: 2px dashed #c09; } +.wait{ outline: 2px solid #c90; } +.good{ outline: 2px solid #9c0; } -.modifOnOff::after { - content: ''; - width: 16px; - height: 16px; - background: #FFF; - position: absolute; - top: 2px; - left: calc(100% + 2px); - border-radius: 100%; - transition: 0.2s; +/***************************/ +/* Message */ +/***************************/ +.message{ + position: fixed; + bottom: 100%; + left: 50%; + z-index: 10; + padding: 20px; + border-radius: 0 0 10px 10px; + background: #ec7068; + background: #90c; + color: #FFF; + font-size: 24px; + animation: message 3s; + transform: translate(-50%, 0); } - -.modifOnOff.active::before { - background: #9c0; +@keyframes message{ + 20%{transform: translate(-50%, 100%)} + 80%{transform: translate(-50%, 100%)} } - -.modifOnOff.active::after { - transform: translateX(20px); -} \ No newline at end of file diff --git a/app/static/js/table_editor.js b/app/static/js/table_editor.js index 692268afb..c2ed4210a 100644 --- a/app/static/js/table_editor.js +++ b/app/static/js/table_editor.js @@ -1,34 +1,6 @@ -/* table_editor, par Sébastien L. +/* table_editor, par Sébastien L. 2021-11-12 */ -/******************************/ -/* Gestion de la modification */ -/******************************/ - -function editableOnOff() { - if (this.classList.toggle("active")) { - document.querySelectorAll("[data-editable=true]").forEach(cellule => { - cellule.contentEditable = true; - cellule.addEventListener("input", delayBeforeSave); - cellule.addEventListener("blur", save); - }) - } else { - document.querySelectorAll("[data-editable=true]").forEach(cellule => { - cellule.removeAttribute("contentEditable"); - cellule.removeEventListener("input", delayBeforeSave); - cellule.removeEventListener("blur", save); - }) - } -} - -let timeout = 0; - -function delayBeforeSave() { - clearTimeout(timeout); - document.querySelector(".wait").classList.add("go"); - timeout = setTimeout(() => { save(this) }, 2000); -} - /*****************************/ /* Mise en place des données */ /*****************************/ @@ -38,19 +10,117 @@ function build_table(data) { data.forEach((cellule) => { output += `
${cellule.data}
`; }) document.querySelector(".tableau").innerHTML = output; - document.querySelector(".modifOnOff").addEventListener("click", editableOnOff); -} \ No newline at end of file + installListeners(); +} + +/*****************************/ +/* Gestion des évènements */ +/*****************************/ +$(function () { + document.body.addEventListener("keydown", key); +}); +function installListeners() { + document.querySelectorAll("[data-editable=true]").forEach(cellule => { + cellule.addEventListener("click", function () { selectCell(this) }); + cellule.addEventListener("dblclick", function () { modifCell(this) }); + }); +} + + +/*********************************/ +/* Interaction avec les cellules */ +/*********************************/ +function selectCell(obj) { + if (obj.classList.contains("modifying")) { + return; // Cellule en cours de modification, ne pas sélectionner. + } + let currentModif = document.querySelector(".modifying"); + if (currentModif) { + if (!save(currentModif)) { + return; + } + } + + document.querySelectorAll(".selected, .modifying").forEach(cellule => { + cellule.classList.remove("selected", "modifying"); + cellule.removeAttribute("contentEditable"); + cellule.removeEventListener("keydown", keyCell); + }) + obj.classList.add("selected"); +} + +function modifCell(obj) { + if (obj) { + obj.classList.add("modifying"); + obj.contentEditable = true; + obj.addEventListener("keydown", keyCell); + obj.focus(); + } +} + +function key(event) { + switch (event.key) { + case "Enter": modifCell(document.querySelector(".selected")); event.preventDefault(); break; + case "ArrowRight": ArrowMove(1, 0); break; + case "ArrowLeft": ArrowMove(-1, 0); break; + case "ArrowUp": ArrowMove(0, -1); break; + case "ArrowDown": ArrowMove(0, 1); break; + } +} + +function ArrowMove(x, y) { + if (document.querySelector(".modifying") || !document.querySelector(".selected")) { + return; // S'il n'y a aucune cellule selectionnée ou si une cellule est encours de modification, on ne change pas + } + + let selected = document.querySelector(".selected"); + let next = document.querySelector(`[data-x="${parseInt(selected.dataset.x) + x}"][data-y="${parseInt(selected.dataset.y) + y}"][data-editable="true"]`); + + if (next) { + selectCell(next); + } +} + +function keyCell(event) { + if (event.key == "Enter") { + event.preventDefault(); + event.stopPropagation(); + if (!save(this)) { + return + } + this.classList.remove("modifying"); + ArrowMove(0, 1); + } +} + +/******************************/ +/* Affichage d'un message */ +/******************************/ +function message(msg) { + var div = document.createElement("div"); + div.className = "message"; + div.innerHTML = msg; + document.querySelector("body").appendChild(div); + setTimeout(() => { + div.remove(); + }, 3000); +} diff --git a/app/templates/pn/form_modules_ue_coefs.html b/app/templates/pn/form_modules_ue_coefs.html index 7c26f021a..e8f671bd8 100644 --- a/app/templates/pn/form_modules_ue_coefs.html +++ b/app/templates/pn/form_modules_ue_coefs.html @@ -13,10 +13,8 @@

Formation {{formation.titre}} ({{formation.acronyme}}) - [version {{formation.version}}] code {{formation.code}}

- -
-
Modifier
+ [version {{formation.version}}] code {{formation.code}} +