Panneaux flottants en plein écran par défaut, avec bouton pour en sortir
Chaque panneau (Nouvel objet, Modifier un objet, Ajouter un champ, Ajouter une entrée) s'ouvre désormais en plein écran par défaut (marge de 12px) plutôt qu'en petite fenêtre centrée — plus confortable dès qu'il y a plusieurs champs/entrées à voir en même temps. Un bouton ⛶ dans l'en-tête bascule vers/depuis la taille et la position précédentes (mémorisées le temps de la session, pas persistées), pour qui préfère un panneau plus petit à côté du reste du tableau de bord. makeFloatPanelFullscreenable(panel, toggleBtn) — générique, posée sur panel._fsToggle — appelée par les 4 familles de panneaux existantes. makeFloatPanelDraggable()/makeFloatPanelResizable() sortent d'abord proprement du plein écran si l'utilisateur interagit manuellement (glisser l'en-tête ou tirer le coin) : sans ça, bottom/right encore actifs en plein écran auraient repris la main sur la position/taille qu'on vient de poser. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
03db681022
commit
943bf265de
@@ -206,6 +206,11 @@ body.builderBody > main.content{ flex:1 1 auto; min-height:0; overflow:hidden; d
|
|||||||
.floatPanel--left{ left:24px; width:280px; }
|
.floatPanel--left{ left:24px; width:280px; }
|
||||||
.floatPanel--right{ right:24px; width:340px; }
|
.floatPanel--right{ right:24px; width:340px; }
|
||||||
.floatPanel--center{ left:50%; width:560px; max-width:calc(100vw - 48px); transform:translateX(-50%); }
|
.floatPanel--center{ left:50%; width:560px; max-width:calc(100vw - 48px); transform:translateX(-50%); }
|
||||||
|
/* Plein écran (voir makeFloatPanelFullscreenable() dans game_dashboard.html)
|
||||||
|
— juste un repère visuel (bordure accent) sur le panneau agrandi, tout le
|
||||||
|
positionnement réel est posé directement en style inline par le JS (pour
|
||||||
|
pouvoir revenir exactement à la position/taille d'avant en sortant). */
|
||||||
|
.floatPanel--fullscreen{ border-color:var(--accent); }
|
||||||
.floatPanelHeader{
|
.floatPanelHeader{
|
||||||
display:flex; align-items:center; justify-content:space-between; gap:8px;
|
display:flex; align-items:center; justify-content:space-between; gap:8px;
|
||||||
padding:8px 10px; border-bottom:1px solid var(--border); background:var(--panel2);
|
padding:8px 10px; border-bottom:1px solid var(--border); background:var(--panel2);
|
||||||
|
|||||||
@@ -221,6 +221,7 @@
|
|||||||
<div class="floatPanel floatPanel--center hidden" id="newObjectPanel">
|
<div class="floatPanel floatPanel--center hidden" id="newObjectPanel">
|
||||||
<div class="floatPanelHeader" id="newObjectPanelHeader">
|
<div class="floatPanelHeader" id="newObjectPanelHeader">
|
||||||
<span class="floatPanelTitle">⋮⋮ Nouvel objet</span>
|
<span class="floatPanelTitle">⋮⋮ Nouvel objet</span>
|
||||||
|
<button type="button" class="button is-small floatPanelFullscreenBtn" title="Plein écran">⛶</button>
|
||||||
<button type="button" class="button is-small" onclick="closeNewObjectPanel()">✕</button>
|
<button type="button" class="button is-small" onclick="closeNewObjectPanel()">✕</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="floatPanelBody">
|
<div class="floatPanelBody">
|
||||||
@@ -261,6 +262,7 @@
|
|||||||
<div class="floatPanel floatPanel--center hidden objectEditPanel" data-definition-id="{{ d.id }}" id="objectEditPanel-{{ d.id }}">
|
<div class="floatPanel floatPanel--center hidden objectEditPanel" data-definition-id="{{ d.id }}" id="objectEditPanel-{{ d.id }}">
|
||||||
<div class="floatPanelHeader">
|
<div class="floatPanelHeader">
|
||||||
<span class="floatPanelTitle">⋮⋮ {{ definition.name }}</span>
|
<span class="floatPanelTitle">⋮⋮ {{ definition.name }}</span>
|
||||||
|
<button type="button" class="button is-small floatPanelFullscreenBtn" title="Plein écran">⛶</button>
|
||||||
<button type="button" class="button is-small" onclick="closeObjectEditPanel({{ d.id }})">✕</button>
|
<button type="button" class="button is-small" onclick="closeObjectEditPanel({{ d.id }})">✕</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="floatPanelBody">
|
<div class="floatPanelBody">
|
||||||
@@ -458,6 +460,7 @@
|
|||||||
<div class="floatPanel floatPanel--center hidden addFieldPanel" data-definition-id="{{ d.id }}" id="addFieldPanel-{{ d.id }}">
|
<div class="floatPanel floatPanel--center hidden addFieldPanel" data-definition-id="{{ d.id }}" id="addFieldPanel-{{ d.id }}">
|
||||||
<div class="floatPanelHeader">
|
<div class="floatPanelHeader">
|
||||||
<span class="floatPanelTitle">⋮⋮ Ajouter un champ — {{ definition.name }}</span>
|
<span class="floatPanelTitle">⋮⋮ Ajouter un champ — {{ definition.name }}</span>
|
||||||
|
<button type="button" class="button is-small floatPanelFullscreenBtn" title="Plein écran">⛶</button>
|
||||||
<button type="button" class="button is-small" onclick="closeAddFieldPanel({{ d.id }})">✕</button>
|
<button type="button" class="button is-small" onclick="closeAddFieldPanel({{ d.id }})">✕</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="floatPanelBody">
|
<div class="floatPanelBody">
|
||||||
@@ -509,6 +512,7 @@
|
|||||||
<div class="floatPanel floatPanel--center hidden addEntryPanel" data-definition-id="{{ d.id }}" id="addEntryPanel-{{ d.id }}">
|
<div class="floatPanel floatPanel--center hidden addEntryPanel" data-definition-id="{{ d.id }}" id="addEntryPanel-{{ d.id }}">
|
||||||
<div class="floatPanelHeader">
|
<div class="floatPanelHeader">
|
||||||
<span class="floatPanelTitle">⋮⋮ Ajouter une entrée — {{ definition.name }}</span>
|
<span class="floatPanelTitle">⋮⋮ Ajouter une entrée — {{ definition.name }}</span>
|
||||||
|
<button type="button" class="button is-small floatPanelFullscreenBtn" title="Plein écran">⛶</button>
|
||||||
<button type="button" class="button is-small" onclick="closeAddEntryPanel({{ d.id }})">✕</button>
|
<button type="button" class="button is-small" onclick="closeAddEntryPanel({{ d.id }})">✕</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="floatPanelBody">
|
<div class="floatPanelBody">
|
||||||
@@ -628,10 +632,15 @@ function makeFloatPanelDraggable(panel, header) {
|
|||||||
header.addEventListener('mousedown', function (e) {
|
header.addEventListener('mousedown', function (e) {
|
||||||
if (e.target.closest('button')) return;
|
if (e.target.closest('button')) return;
|
||||||
dragging = true;
|
dragging = true;
|
||||||
|
// Glisser un panneau en plein écran doit d'abord l'en faire sortir —
|
||||||
|
// sinon left/top posés juste en dessous seraient aussitôt repris en
|
||||||
|
// main par bottom/right encore actifs (voir makeFloatPanelFullscreenable).
|
||||||
|
if (panel.classList.contains('floatPanel--fullscreen')) panel._fsToggle.exit();
|
||||||
var rect = panel.getBoundingClientRect();
|
var rect = panel.getBoundingClientRect();
|
||||||
panel.style.left = rect.left + 'px';
|
panel.style.left = rect.left + 'px';
|
||||||
panel.style.top = rect.top + 'px';
|
panel.style.top = rect.top + 'px';
|
||||||
panel.style.right = 'auto';
|
panel.style.right = 'auto';
|
||||||
|
panel.style.bottom = 'auto';
|
||||||
panel.style.transform = 'none';
|
panel.style.transform = 'none';
|
||||||
offsetX = e.clientX - rect.left;
|
offsetX = e.clientX - rect.left;
|
||||||
offsetY = e.clientY - rect.top;
|
offsetY = e.clientY - rect.top;
|
||||||
@@ -651,6 +660,10 @@ function makeFloatPanelResizable(panel, handle) {
|
|||||||
var resizing = false, startX = 0, startY = 0, startW = 0, startH = 0;
|
var resizing = false, startX = 0, startY = 0, startW = 0, startH = 0;
|
||||||
handle.addEventListener('mousedown', function (e) {
|
handle.addEventListener('mousedown', function (e) {
|
||||||
resizing = true;
|
resizing = true;
|
||||||
|
// Même remarque que pour le glisser-déposer : sortir du plein écran
|
||||||
|
// d'abord, sinon bottom/right encore actifs reprendraient la main sur
|
||||||
|
// la largeur/hauteur posées ci-dessous.
|
||||||
|
if (panel.classList.contains('floatPanel--fullscreen')) panel._fsToggle.exit();
|
||||||
var rect = panel.getBoundingClientRect();
|
var rect = panel.getBoundingClientRect();
|
||||||
startX = e.clientX; startY = e.clientY;
|
startX = e.clientX; startY = e.clientY;
|
||||||
startW = rect.width; startH = rect.height;
|
startW = rect.width; startH = rect.height;
|
||||||
@@ -673,13 +686,50 @@ function makeFloatPanelResizable(panel, handle) {
|
|||||||
document.body.style.userSelect = '';
|
document.body.style.userSelect = '';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// Plein écran (voir switchDashTab pour l'esprit général : chaque panneau
|
||||||
|
// s'ouvre en plein écran par défaut — plus pratique dès qu'il y a plus de
|
||||||
|
// quelques champs — avec un bouton pour revenir à sa taille/position
|
||||||
|
// précédente, mémorisée le temps de la session (pas persistée). Renvoie un
|
||||||
|
// objet {enter, exit} et pose panel._fsToggle dessus, pour que le code qui
|
||||||
|
// OUVRE le panneau (openXxxPanel ci-dessous) puisse appeler enter() sans
|
||||||
|
// avoir à re-chercher le bouton.
|
||||||
|
function makeFloatPanelFullscreenable(panel, toggleBtn) {
|
||||||
|
var saved = null;
|
||||||
|
function enter() {
|
||||||
|
saved = {
|
||||||
|
left: panel.style.left, top: panel.style.top, right: panel.style.right,
|
||||||
|
width: panel.style.width, height: panel.style.height,
|
||||||
|
maxWidth: panel.style.maxWidth, transform: panel.style.transform,
|
||||||
|
};
|
||||||
|
panel.classList.add('floatPanel--fullscreen');
|
||||||
|
panel.style.left = '12px'; panel.style.top = '12px'; panel.style.right = '12px'; panel.style.bottom = '12px';
|
||||||
|
panel.style.width = 'auto'; panel.style.height = 'auto'; panel.style.maxWidth = 'none'; panel.style.transform = 'none';
|
||||||
|
toggleBtn.title = 'Quitter le plein écran';
|
||||||
|
}
|
||||||
|
function exit() {
|
||||||
|
panel.classList.remove('floatPanel--fullscreen');
|
||||||
|
panel.style.bottom = '';
|
||||||
|
if (saved) {
|
||||||
|
panel.style.left = saved.left; panel.style.top = saved.top; panel.style.right = saved.right;
|
||||||
|
panel.style.width = saved.width; panel.style.height = saved.height;
|
||||||
|
panel.style.maxWidth = saved.maxWidth; panel.style.transform = saved.transform;
|
||||||
|
}
|
||||||
|
toggleBtn.title = 'Plein écran';
|
||||||
|
}
|
||||||
|
toggleBtn.addEventListener('click', function () {
|
||||||
|
if (panel.classList.contains('floatPanel--fullscreen')) exit(); else enter();
|
||||||
|
});
|
||||||
|
panel._fsToggle = { enter: enter, exit: exit };
|
||||||
|
return panel._fsToggle;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------- Panneau déplaçable "Nouvel objet" ----------
|
// ---------- Panneau déplaçable "Nouvel objet" ----------
|
||||||
(function () {
|
(function () {
|
||||||
var panel = document.getElementById('newObjectPanel');
|
var panel = document.getElementById('newObjectPanel');
|
||||||
makeFloatPanelDraggable(panel, document.getElementById('newObjectPanelHeader'));
|
makeFloatPanelDraggable(panel, document.getElementById('newObjectPanelHeader'));
|
||||||
makeFloatPanelResizable(panel, document.getElementById('newObjectPanelResizeHandle'));
|
makeFloatPanelResizable(panel, document.getElementById('newObjectPanelResizeHandle'));
|
||||||
window.openNewObjectPanel = function () { panel.classList.remove('hidden'); };
|
makeFloatPanelFullscreenable(panel, panel.querySelector('.floatPanelFullscreenBtn'));
|
||||||
|
window.openNewObjectPanel = function () { panel.classList.remove('hidden'); panel._fsToggle.enter(); };
|
||||||
window.closeNewObjectPanel = function () { panel.classList.add('hidden'); };
|
window.closeNewObjectPanel = function () { panel.classList.add('hidden'); };
|
||||||
})();
|
})();
|
||||||
|
|
||||||
@@ -688,10 +738,13 @@ function makeFloatPanelResizable(panel, handle) {
|
|||||||
document.querySelectorAll('.objectEditPanel').forEach(function (panel) {
|
document.querySelectorAll('.objectEditPanel').forEach(function (panel) {
|
||||||
makeFloatPanelDraggable(panel, panel.querySelector('.floatPanelHeader'));
|
makeFloatPanelDraggable(panel, panel.querySelector('.floatPanelHeader'));
|
||||||
makeFloatPanelResizable(panel, panel.querySelector('.floatPanelResizeHandle'));
|
makeFloatPanelResizable(panel, panel.querySelector('.floatPanelResizeHandle'));
|
||||||
|
makeFloatPanelFullscreenable(panel, panel.querySelector('.floatPanelFullscreenBtn'));
|
||||||
});
|
});
|
||||||
window.openObjectEditPanel = function (definitionId, subtab) {
|
window.openObjectEditPanel = function (definitionId, subtab) {
|
||||||
document.querySelectorAll('.objectEditPanel').forEach(function (panel) {
|
document.querySelectorAll('.objectEditPanel').forEach(function (panel) {
|
||||||
panel.classList.toggle('hidden', panel.dataset.definitionId !== String(definitionId));
|
var isTarget = panel.dataset.definitionId === String(definitionId);
|
||||||
|
panel.classList.toggle('hidden', !isTarget);
|
||||||
|
if (isTarget) panel._fsToggle.enter();
|
||||||
});
|
});
|
||||||
if (subtab) {
|
if (subtab) {
|
||||||
var panel = document.querySelector('.objectEditPanel[data-definition-id="' + definitionId + '"]');
|
var panel = document.querySelector('.objectEditPanel[data-definition-id="' + definitionId + '"]');
|
||||||
@@ -725,6 +778,7 @@ function makeFloatPanelResizable(panel, handle) {
|
|||||||
document.querySelectorAll('.addFieldPanel').forEach(function (panel) {
|
document.querySelectorAll('.addFieldPanel').forEach(function (panel) {
|
||||||
makeFloatPanelDraggable(panel, panel.querySelector('.floatPanelHeader'));
|
makeFloatPanelDraggable(panel, panel.querySelector('.floatPanelHeader'));
|
||||||
makeFloatPanelResizable(panel, panel.querySelector('.floatPanelResizeHandle'));
|
makeFloatPanelResizable(panel, panel.querySelector('.floatPanelResizeHandle'));
|
||||||
|
makeFloatPanelFullscreenable(panel, panel.querySelector('.floatPanelFullscreenBtn'));
|
||||||
|
|
||||||
var typeSelect = panel.querySelector('.fieldTypeSelect');
|
var typeSelect = panel.querySelector('.fieldTypeSelect');
|
||||||
var relationTarget = panel.querySelector('.relationTarget');
|
var relationTarget = panel.querySelector('.relationTarget');
|
||||||
@@ -739,11 +793,12 @@ function makeFloatPanelResizable(panel, handle) {
|
|||||||
document.querySelectorAll('.addEntryPanel').forEach(function (panel) {
|
document.querySelectorAll('.addEntryPanel').forEach(function (panel) {
|
||||||
makeFloatPanelDraggable(panel, panel.querySelector('.floatPanelHeader'));
|
makeFloatPanelDraggable(panel, panel.querySelector('.floatPanelHeader'));
|
||||||
makeFloatPanelResizable(panel, panel.querySelector('.floatPanelResizeHandle'));
|
makeFloatPanelResizable(panel, panel.querySelector('.floatPanelResizeHandle'));
|
||||||
|
makeFloatPanelFullscreenable(panel, panel.querySelector('.floatPanelFullscreenBtn'));
|
||||||
});
|
});
|
||||||
|
|
||||||
window.openAddFieldPanel = function (definitionId) {
|
window.openAddFieldPanel = function (definitionId) {
|
||||||
var panel = document.querySelector('.addFieldPanel[data-definition-id="' + definitionId + '"]');
|
var panel = document.querySelector('.addFieldPanel[data-definition-id="' + definitionId + '"]');
|
||||||
if (panel) panel.classList.remove('hidden');
|
if (panel) { panel.classList.remove('hidden'); panel._fsToggle.enter(); }
|
||||||
};
|
};
|
||||||
window.closeAddFieldPanel = function (definitionId) {
|
window.closeAddFieldPanel = function (definitionId) {
|
||||||
var panel = document.querySelector('.addFieldPanel[data-definition-id="' + definitionId + '"]');
|
var panel = document.querySelector('.addFieldPanel[data-definition-id="' + definitionId + '"]');
|
||||||
@@ -751,7 +806,7 @@ function makeFloatPanelResizable(panel, handle) {
|
|||||||
};
|
};
|
||||||
window.openAddEntryPanel = function (definitionId) {
|
window.openAddEntryPanel = function (definitionId) {
|
||||||
var panel = document.querySelector('.addEntryPanel[data-definition-id="' + definitionId + '"]');
|
var panel = document.querySelector('.addEntryPanel[data-definition-id="' + definitionId + '"]');
|
||||||
if (panel) panel.classList.remove('hidden');
|
if (panel) { panel.classList.remove('hidden'); panel._fsToggle.enter(); }
|
||||||
};
|
};
|
||||||
window.closeAddEntryPanel = function (definitionId) {
|
window.closeAddEntryPanel = function (definitionId) {
|
||||||
var panel = document.querySelector('.addEntryPanel[data-definition-id="' + definitionId + '"]');
|
var panel = document.querySelector('.addEntryPanel[data-definition-id="' + definitionId + '"]');
|
||||||
|
|||||||
Reference in New Issue
Block a user