Nouvelle version table_editor (via Seb. L.)

This commit is contained in:
Emmanuel Viennet 2021-11-13 09:11:00 +01:00
parent c0dd83fadb
commit 477c2efac9
3 changed files with 161 additions and 111 deletions

View File

@ -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;
}
.modifOnOff.active::after {
transform: translateX(20px);
@keyframes message{
20%{transform: translate(-50%, 100%)}
80%{transform: translate(-50%, 100%)}
}

View File

@ -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 += `
<div
class="${cellule.style}"
class="${cellule.style || ""}"
data-editable="${cellule.editable || "false"}"
data-module_id="${cellule.module_id}"
data-ue_id="${cellule.ue_id}"
data-x="${cellule.x}"
data-y="${cellule.y}"
data-nbX="${cellule.nbX || 1}"
data-nbY="${cellule.nbY || 1}"
data-data="${cellule.data}"
style="
--x:${cellule.x};
--y:${cellule.y};
--nbX:${cellule.nbX};
--nbY: ${cellule.nbY};
--nbX:${cellule.nbX || 1};
--nbY: ${cellule.nbY || 1};
">
${cellule.data}
</div>`;
})
document.querySelector(".tableau").innerHTML = output;
document.querySelector(".modifOnOff").addEventListener("click", editableOnOff);
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);
}

View File

@ -15,8 +15,6 @@
<h2>Formation {{formation.titre}} ({{formation.acronyme}})
[version {{formation.version}}] code {{formation.code}}</h2>
<div class=wait></div>
<div class=modifOnOff>Modifier</div>
<div class="tableau"></div>
<script>
@ -26,15 +24,24 @@
});
});
function save(obj) {
if (event?.currentTarget) {
obj = event.currentTarget;
var value = obj.innerText.trim();
if (value.length == 0) {
value = "0";
}
document.querySelector(".wait").classList.remove("go");
if (!/^\d+$/.test(value)) {
message("Il est attendu un nombre");
return false;
}
if (value == obj.dataset.data) {
return true; // Aucune modification, pas d'enregistrement mais on continue normalement
}
obj.dataset.data = value;
obj.classList.add("wait");
// XXX DEBUG
console.log(`
x : ${getComputedStyle(obj).getPropertyValue("--x")}
y : ${getComputedStyle(obj).getPropertyValue("--y")}
data : ${obj.innerText}
data : ${value}
ue_id: ${obj.dataset.ue_id}
module_id : ${obj.dataset.module_id}
`);
@ -42,10 +49,17 @@
{
module_id: `${obj.dataset.module_id}`,
ue_id: `${obj.dataset.ue_id}`,
coef: `${obj.innerText}`
coef: `${value}`
},
function (result) {
console.log("enregistré");
console.log("enregistré"); // XXX
obj.classList.remove("wait");
obj.classList.add("good");
// Lorsque les données sont bien enregistrés, on enlève
// l'indication que c'est bon au bout d'un temps
setTimeout(() => {
obj.classList.remove("good");
}, 1000);
}
);
}