template html & css

This commit is contained in:
ph
2025-11-26 22:34:43 +01:00
commit ea21779b05
20 changed files with 3208 additions and 0 deletions

445
css/interface_glisser.html Normal file
View File

@@ -0,0 +1,445 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Interface glisser</title>
<style>
/* Le conteneur parent pour toute l'application */
.app-layout {
display: grid;
/* Définit une grille de 2 colonnes (250px et le reste) */
grid-template-columns: 250px 1fr;
/* Définit 3 lignes de haut en bas */
grid-template-rows: auto 1fr auto;
/* Attribue un nom à chaque zone de la grille */
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
/* Assure que la grille prend toute la hauteur visible */
min-height: 100vh;
}
/* 1. Placement des zones */
.header {
grid-area: header;
background-color: #333;
color: white;
padding: 10px;
}
.sidebar {
grid-area: sidebar;
background-color: #f4f4f4;
padding: 15px;
border-right: 1px solid #ccc;
}
.content-area {
grid-area: content;
padding: 20px;
/* Le défilement se produit ici si le contenu dépasse la hauteur */
overflow-y: auto;
}
/* Style appliqué à la zone de contenu quand on glisse un élément dessus */
.content-area.drag-over {
border: 2px dashed #007bff;
background-color: #f0f8ff;
}
/* Style appliqué à l'élément fantôme pendant le glissement */
.dynamic-item-dragging {
opacity: 0.5;
}
.dynamic-item {
/* Rendre l'élément visuellement déplaçable */
cursor: grab;
/* Espacement pour séparer les éléments */
margin-bottom: 10px;
padding: 5px;
/* Indication visuelle subtile */
border: 1px solid #eee;
border-radius: 4px;
}
.footer {
grid-area: footer;
background-color: #333;
color: white;
padding: 10px;
text-align: center;
}
/* Styles pour les éléments internes (textes, boutons, etc.) */
.content-area button {
padding: 10px 15px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
}
.dynamic-text {
padding: 10px;
margin: 10px 0;
background-color: #e6f7ff;
border: 1px solid #b3e0ff;
cursor: grab;
/* Indique que l'élément peut être déplacé */
}
.dynamic-button {
padding: 10px 15px;
margin: 5px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.dynamic-combobox {
/* sur la même ligne */
display: inline-block;
padding: 8px 12px;
margin: 10px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: white;
font-size: 16px;
/* Pour qu'elle prenne sa propre ligne
display: block; */
}
/* liste */
.dynamic-list {
/* sur la même ligne */
display: inline-block;
margin: 15px 0 15px 20px;
padding: 10px;
border: 1px solid #dcdcdc;
background-color: #fafafa;
/* Barre de couleur sur le côté */
border-left: 15px solid #007bff;
width: 200px;
}
.dynamic-list li {
margin-bottom: 5px;
padding: 2px;
}
/* tableau */
.dynamic-table {
width: 80%;
/* Prend 80% de la largeur du conteneur */
border-collapse: collapse;
/* Joint les bordures des cellules */
margin: 20px 0;
font-family: sans-serif;
}
.dynamic-table th,
.dynamic-table td {
border: 1px solid #ccc;
padding: 8px;
text-align: left;
/* MODIFICATION CLÉ */
}
.dynamic-table th {
background-color: #f2f2f2;
color: #333;
font-weight: bold;
}
</style>
<script>
let index = 0;
document.addEventListener('DOMContentLoaded', function () {
// 1. Cible l'endroit où les nouveaux éléments seront insérés
const contentArea = document.getElementById('content-area');
// 2. Cible les boutons de contrôle dans la sidebar
const addTextBtn = document.getElementById('add-text-btn');
const addButtonBtn = document.getElementById('add-button-btn');
const addComboboxBtn = document.getElementById('add-cb-btn');
const addListBtn = document.getElementById('add-list-btn');
const addTableBtn = document.getElementById('add-table-btn');
// --- Fonction pour ajouter un Paragraphe ---
addTextBtn.addEventListener('click', function () {
// Créer un nouvel élément <p>
const newParagraph = document.createElement('p');
// Lui donner du contenu et des styles
newParagraph.textContent = 'Nouveau paragraphe ajouté dynamiquement.';
newParagraph.className = 'dynamic-item dynamic-text';
newParagraph.setAttribute('draggable', 'true');
// Insérer l'élément dans la zone de contenu
contentArea.appendChild(newParagraph);
// Optionnel : rendre le texte éditable (clic pour modifier)
newParagraph.setAttribute('contenteditable', 'true');
});
// --- Fonction pour ajouter un Bouton ---
addButtonBtn.addEventListener('click', function () {
// Créer un nouvel élément <button>
const newButton = document.createElement('button');
// Lui donner du contenu et des styles
newButton.textContent = 'Bouton ' + Number(++index);
newButton.className = 'dynamic-item dynamic-button';
newButton.setAttribute('draggable', 'true');
// Insérer l'élément dans la zone de contenu
contentArea.appendChild(newButton);
});
addComboboxBtn.addEventListener('click', function () {
// 1. Création de l'élément <select> (la combobox)
const newSelect = document.createElement('select');
newSelect.className = 'dynamic-item dynamic-combobox';
newSelect.setAttribute('draggable', 'true');
newSelect.id = 'combobox-' + Date.now(); // Donne un ID unique
// 2. Création des options
// Option par défaut/neutre
const defaultOption = document.createElement('option');
defaultOption.textContent = 'Sélectionnez une option';
defaultOption.value = '';
defaultOption.disabled = true;
defaultOption.selected = true;
newSelect.appendChild(defaultOption);
// Option 1
const option1 = document.createElement('option');
option1.textContent = 'Choix ' + Number(++index) ;
option1.value = 'a';
newSelect.appendChild(option1);
// Option 2
const option2 = document.createElement('option');
option2.textContent = 'Choix ' + Number(++index);
option2.value = 'b';
newSelect.appendChild(option2);
// Option 3
const option3 = document.createElement('option');
option3.textContent = 'Choix ' + Number(++index);
option3.value = 'c';
newSelect.appendChild(option3);
// 3. Insérer la combobox dans la zone de contenu
contentArea.appendChild(newSelect);
});
addListBtn.addEventListener('click', function () {
// 1. Création de l'élément parent de la liste (non ordonnée)
const newList = document.createElement('ul');
newList.className = 'dynamic-item dynamic-list';
newList.setAttribute('draggable', 'true');
newList.id = 'list-' + Date.now(); // ID unique
// 2. Création et ajout des éléments de la liste (<li>)
// Élément 1
const item1 = document.createElement('li');
item1.textContent = 'Item ' + Number(++index);
// Rendre le contenu éditable pour l'interface visuelle
item1.setAttribute('contenteditable', 'true');
newList.appendChild(item1);
// Élément 2
const item2 = document.createElement('li');
item2.textContent = 'Item ' + Number(++index);
item2.setAttribute('contenteditable', 'true');
newList.appendChild(item2);
// Élément 3
const item3 = document.createElement('li');
item3.textContent = 'Item ' + Number(++index);
item3.setAttribute('contenteditable', 'true');
newList.appendChild(item3);
// 3. Insérer la liste complète dans la zone de contenu
contentArea.appendChild(newList);
});
addTableBtn.addEventListener('click', function () {
// 1. Création de l'élément parent <table>
const newTable = document.createElement('table');
newTable.className = 'dynamic-item dynamic-table';
newTable.setAttribute('draggable', 'true');
newTable.id = 'table-' + Date.now(); // ID unique
// 2. Création de l'en-tête du tableau (<thead>)
const tableHead = newTable.createTHead();
const headerRow = tableHead.insertRow();
// Ajout des cellules d'en-tête (<th>)
['Nom', 'Âge', 'Ville'].forEach(headerText => {
let th = document.createElement('th');
th.textContent = headerText;
headerRow.appendChild(th);
});
// 3. Création du corps du tableau (<tbody>)
const tableBody = newTable.createTBody();
// Données à insérer
const data = [
['Alice ' + Number(++index), 28, 'Paris'],
['Bob ' + Number(++index), 35, 'Lyon']
];
// Ajout des lignes de données (<tr>)
data.forEach(rowData => {
const row = tableBody.insertRow();
rowData.forEach(cellData => {
const cell = row.insertCell();
cell.textContent = cellData;
// Rendre les cellules éditables
cell.setAttribute('contenteditable', 'true');
});
});
// 4. Insérer le tableau complet dans la zone de contenu
contentArea.appendChild(newTable);
});
// --- (Optionnel) Ajout de la logique de Glisser-Déposer ---
// Le vrai "glisser-déposer" (drag-and-drop) nécessite beaucoup plus de code
// (utilisation des événements dragstart, dragover, drop...) pour être implémenté.
// L'exemple ci-dessus est la méthode "Ajout par clic" qui est plus simple.
let draggedItem = null; // Variable globale pour stocker l'élément en cours de glissement
// ----------------------------------------------------------------
// A. RENDRE LES ÉLÉMENTS GLISSABLES (Drag Start)
// ----------------------------------------------------------------
// On utilise la délégation d'événement sur le conteneur parent
contentArea.addEventListener('dragstart', function (e) {
// Vérifie si l'élément glissé est un élément que nous voulons déplacer
if (e.target.closest('.dynamic-item')) {
draggedItem = e.target.closest('.dynamic-item');
// Ajoute une classe pour l'effet visuel de glissement (opacité)
setTimeout(() => {
draggedItem.classList.add('dynamic-item-dragging');
}, 0);
// Stocke l'ID ou toute autre donnée dans l'objet de transfert de données
e.dataTransfer.setData('text/plain', draggedItem.id || 'dynamic-item');
e.dataTransfer.effectAllowed = 'move';
}
});
contentArea.addEventListener('dragend', function (e) {
// Retire la classe quand le glissement est terminé (réussi ou annulé)
e.target.classList.remove('dynamic-item-dragging');
draggedItem = null;
});
// ----------------------------------------------------------------
// B. GÉRER LA ZONE DE DÉPÔT (Drag Over & Drop)
// ----------------------------------------------------------------
// Empêche le comportement par défaut (qui est de ne pas autoriser le dépôt)
contentArea.addEventListener('dragover', function (e) {
e.preventDefault();
contentArea.classList.add('drag-over');
e.dataTransfer.dropEffect = 'move';
// Logique de positionnement (où déposer l'élément)
if (draggedItem && e.target.closest('.dynamic-item') && e.target.closest('.dynamic-item') !== draggedItem) {
const currentHoveredItem = e.target.closest('.dynamic-item');
// Calcule si le curseur est dans la moitié supérieure ou inférieure de l'élément survolé
const rect = currentHoveredItem.getBoundingClientRect();
const midpoint = rect.y + rect.height / 2;
// Si le curseur est dans la moitié supérieure, on insère AVANT
if (e.clientY < midpoint) {
contentArea.insertBefore(draggedItem, currentHoveredItem);
}
// Sinon, on insère APRÈS l'élément suivant
else {
contentArea.insertBefore(draggedItem, currentHoveredItem.nextSibling);
}
}
});
// Retire l'indicateur visuel quand l'élément quitte la zone
contentArea.addEventListener('dragleave', function (e) {
// Vérifie que l'on sort bien de la zone de contenu principale
if (e.target === contentArea) {
contentArea.classList.remove('drag-over');
}
});
// Gère le dépôt final
contentArea.addEventListener('drop', function (e) {
e.preventDefault();
contentArea.classList.remove('drag-over');
// La logique d'insertion est déjà gérée dans dragover pour une réorganisation fluide.
// Ici, on pourrait ajouter une logique de sauvegarde ou de confirmation.
if (draggedItem) {
console.log("Élément déposé avec succès !");
draggedItem.classList.remove('dynamic-item-dragging');
draggedItem = null;
}
});
});
</script>
</head>
<body>
<div class="app-layout">
<header class="header">
Votre bandeau du haut
</header>
<aside class="sidebar">
<h3>Outils</h3>
<button id="add-text-btn" class="dynamic-button">Ajouter un Paragraphe</button>
<button id="add-button-btn" class="dynamic-button">Ajouter un Bouton</button>
<button id="add-cb-btn" class="dynamic-button">Ajouter un Combobox</button>
<button id="add-list-btn" class="dynamic-button">Ajouter une liste</button>
<button id="add-table-btn" class="dynamic-button">Ajouter un Tableau</button>
</aside>
<main class="content-area" id="content-area">
<h1>Conteneur Principal</h1>
</main>
<footer class="footer">
Bandeau du bas / Pied de page
</footer>
</div>
</body>
</html>