template html & css
This commit is contained in:
7
css/.vscode/settings.json
vendored
Normal file
7
css/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"workbench.colorCustomizations": {
|
||||
"editor.background": "#d0e1f7", // couleur de fond de l’éditeur
|
||||
"sideBar.background": "#d0e1f7", // couleur de fond de la barre latérale
|
||||
"activityBar.background": "#d0e1f7" // barre d’activité
|
||||
}
|
||||
}
|
||||
102
css/flexbox.html
Normal file
102
css/flexbox.html
Normal file
@@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Flexbox</title>
|
||||
<style>
|
||||
.cluster {
|
||||
width: 1200px;
|
||||
}
|
||||
.flexbox {
|
||||
display: flex;
|
||||
width: 1200px;
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.box {
|
||||
/* en dehors de la division */
|
||||
margin: 4px;
|
||||
/* dans la division */
|
||||
padding: 4px;
|
||||
background-color: #e1dfdf;
|
||||
border: 1px solid black;
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.box_3 {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
|
||||
.flexbox[data-flex-wrap] {
|
||||
/* flex-wrap: wrap; */
|
||||
flex-direction: column
|
||||
}
|
||||
|
||||
.flexbox[data-space] {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.flexbox[data-align-center] {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Presentation styles
|
||||
.flexbox>* {
|
||||
max-width: 500px;
|
||||
}
|
||||
*/
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Ce code s'exécutera seulement après que tout le HTML sera chargé
|
||||
const switches = document.querySelectorAll('[role="switch"]');
|
||||
const flexbox = document.querySelector(".flexbox");
|
||||
|
||||
switches.forEach((item) => {
|
||||
item.addEventListener("change", () => {
|
||||
if (item.checked) {
|
||||
flexbox.setAttribute(`data-${item.getAttribute("id")}`, "");
|
||||
} else {
|
||||
flexbox.removeAttribute(`data-${item.getAttribute("id")}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
</body>
|
||||
<div class="cluster">
|
||||
<div >
|
||||
<label for="flex-wrap">
|
||||
<input type="checkbox" role="switch" id="flex-wrap" />
|
||||
<span>Turn on wrapping</span>
|
||||
|
||||
</label>
|
||||
<label for="align-center">
|
||||
<input type="checkbox" role="switch" id="align-center" />
|
||||
<span>Align items in the center</span>
|
||||
</label>
|
||||
<label for="space">
|
||||
<input type="checkbox" role="switch" id="space" />
|
||||
<span>Add space between</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flexbox">
|
||||
<div class="box">box 1</div>
|
||||
<div class="box">box 2</div>
|
||||
<div class="box box_3">box 3</div>
|
||||
</div>
|
||||
|
||||
</html>
|
||||
108
css/grid.html
Normal file
108
css/grid.html
Normal file
@@ -0,0 +1,108 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Grid</title>
|
||||
<style>
|
||||
.cluster {
|
||||
width: 1200px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
width: 1200px;
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.box {
|
||||
/* Centrage Horizontal du texte/inline (EXISTANT) */
|
||||
text-align: center;
|
||||
|
||||
/* NOUVEAUX STYLES pour le Centrage Vertical */
|
||||
/* 1. Transforme la boîte en conteneur Flex */
|
||||
display: flex;
|
||||
|
||||
/* 2. Centre les éléments enfants sur l'axe vertical (axe croisé) */
|
||||
align-items: center;
|
||||
|
||||
/* 3. Centre les éléments enfants sur l'axe horizontal (axe principal) */
|
||||
/* C'est une alternative à text-align: center; pour les éléments de bloc */
|
||||
justify-content: center;
|
||||
/* dans la division */
|
||||
|
||||
padding: 4px;
|
||||
background-color: #e1dfdf;
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.box_3 {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
|
||||
.flexbox[data-flex-wrap] {
|
||||
/* flex-wrap: wrap; */
|
||||
flex-direction: column
|
||||
}
|
||||
|
||||
.flexbox[data-space] {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.flexbox[data-align-center] {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Presentation styles
|
||||
.flexbox>* {
|
||||
max-width: 500px;
|
||||
}
|
||||
*/
|
||||
</style>
|
||||
|
||||
<script>
|
||||
/*
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Ce code s'exécutera seulement après que tout le HTML sera chargé
|
||||
const switches = document.querySelectorAll('[role="switch"]');
|
||||
const flexbox = document.querySelector(".flexbox");
|
||||
|
||||
switches.forEach((item) => {
|
||||
item.addEventListener("change", () => {
|
||||
if (item.checked) {
|
||||
flexbox.setAttribute(`data-${item.getAttribute("id")}`, "");
|
||||
} else {
|
||||
flexbox.removeAttribute(`data-${item.getAttribute("id")}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
<div class="cluster">
|
||||
<div class="grid">
|
||||
<div class="box">Item 1</div>
|
||||
<div class="box">Item 2</div>
|
||||
<div class="box">Item 3</div>
|
||||
<div class="box">Item 4</div>
|
||||
<div class="box">Item 5</div>
|
||||
<div class="box">Item 6</div>
|
||||
<div class="box">Item 7</div>
|
||||
<div class="box">Item 8</div>
|
||||
<div class="box">Item 9</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</html>
|
||||
93
css/interface_base.html
Normal file
93
css/interface_base.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Interface base </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;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="app-layout">
|
||||
<header class="header">
|
||||
Votre bandeau du haut
|
||||
</header>
|
||||
|
||||
<aside class="sidebar">
|
||||
Panneau latéral (ici, votre "panneau haut")
|
||||
</aside>
|
||||
|
||||
<main class="content-area" >
|
||||
<h1>Conteneur Principal</h1>
|
||||
<p>Ici vous ajoutez vos éléments : textes, boutons, etc.</p>
|
||||
<button>Un bouton</button>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
Bandeau du bas / Pied de page
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
326
css/interface_dynamique.html
Normal file
326
css/interface_dynamique.html
Normal file
@@ -0,0 +1,326 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Interface dynamique</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;
|
||||
}
|
||||
|
||||
.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 {
|
||||
padding: 8px 12px;
|
||||
margin: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
font-size: 16px;
|
||||
display: block;
|
||||
/* Pour qu'elle prenne sa propre ligne */
|
||||
}
|
||||
|
||||
/* liste */
|
||||
.dynamic-list {
|
||||
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;
|
||||
}
|
||||
|
||||
.dynamic-table th {
|
||||
background-color: #f2f2f2;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
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-text';
|
||||
|
||||
// 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 dynamique';
|
||||
newButton.className = 'dynamic-button';
|
||||
|
||||
// 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-combobox';
|
||||
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 A';
|
||||
option1.value = 'a';
|
||||
newSelect.appendChild(option1);
|
||||
|
||||
// Option 2
|
||||
const option2 = document.createElement('option');
|
||||
option2.textContent = 'Choix B';
|
||||
option2.value = 'b';
|
||||
newSelect.appendChild(option2);
|
||||
|
||||
// Option 3
|
||||
const option3 = document.createElement('option');
|
||||
option3.textContent = 'Choix C';
|
||||
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-list';
|
||||
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 = 'Premier élément de la liste';
|
||||
// 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 = 'Deuxième élément de la liste';
|
||||
item2.setAttribute('contenteditable', 'true');
|
||||
newList.appendChild(item2);
|
||||
|
||||
// Élément 3
|
||||
const item3 = document.createElement('li');
|
||||
item3.textContent = 'Troisième élément de la liste';
|
||||
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-table';
|
||||
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', 28, 'Paris'],
|
||||
['Bob', 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.
|
||||
|
||||
});
|
||||
</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>
|
||||
445
css/interface_glisser.html
Normal file
445
css/interface_glisser.html
Normal 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>
|
||||
551
css/interface_glisser_prop.html
Normal file
551
css/interface_glisser_prop.html
Normal file
@@ -0,0 +1,551 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Interface glisser</title>
|
||||
<style>
|
||||
/* Le conteneur parent pour toute l'application */
|
||||
.app-layout {
|
||||
display: grid;
|
||||
/* 3 Colonnes : Sidebar (250px) | Contenu (Reste) | Propriétés (250px) */
|
||||
grid-template-columns: 250px 1fr 250px;
|
||||
/* 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 header"
|
||||
"sidebar content properties-panel"
|
||||
"footer 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;
|
||||
}
|
||||
|
||||
/* Nouveau style pour le panneau de propriétés */
|
||||
.properties-panel {
|
||||
grid-area: properties-panel;
|
||||
background-color: #f9f9f9;
|
||||
padding: 15px;
|
||||
border-left: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.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 appliqué à l'élément actuellement en cours d'édition */
|
||||
.dynamic-item.is-selected {
|
||||
outline: 2px solid #ffaa00;
|
||||
/* Un contour orange pour le marquer */
|
||||
box-shadow: 0 0 5px rgba(255, 170, 0, 0.5);
|
||||
}
|
||||
|
||||
/* Style des contrôles de propriétés */
|
||||
#property-controls label {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#property-controls input {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
let index = 0;
|
||||
let selectedElement = null; // Élément actuellement cliqué
|
||||
|
||||
// 1. Cible l'endroit où les nouveaux éléments seront insérés
|
||||
const contentArea = document.getElementById('content-area');
|
||||
const propertyControls = document.getElementById('property-controls');
|
||||
|
||||
// 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;
|
||||
}
|
||||
});
|
||||
// ----------------------------------------------------------------
|
||||
// A. GESTION DU CLIC SUR UN ÉLÉMENT DYNAMIQUE
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
// Utilisation de la délégation pour capturer les clics sur les éléments
|
||||
contentArea.addEventListener('click', function (e) {
|
||||
// Vérifie si l'élément cliqué est un de nos éléments glissables
|
||||
const clickedItem = e.target.closest('.dynamic-item');
|
||||
|
||||
if (clickedItem) {
|
||||
// Empêche le clic de se propager (si l'élément est un bouton, etc.)
|
||||
e.stopPropagation();
|
||||
|
||||
// 1. Désélectionner l'ancien élément et sélectionner le nouveau
|
||||
if (selectedElement) {
|
||||
selectedElement.classList.remove('is-selected');
|
||||
}
|
||||
selectedElement = clickedItem;
|
||||
selectedElement.classList.add('is-selected');
|
||||
|
||||
// 2. Afficher les contrôles de propriétés
|
||||
displayProperties(selectedElement);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// B. GÉNÉRATION ET GESTION DES CHAMPS D'ENTRÉE (INPUTS)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
function displayProperties(element) {
|
||||
// Vider les anciens contrôles
|
||||
propertyControls.innerHTML = '';
|
||||
|
||||
// 1. Contrôle du Texte (Pour tous les éléments avec du texte)
|
||||
if (element.textContent) {
|
||||
propertyControls.innerHTML += `
|
||||
<label for="prop-text">Texte :</label>
|
||||
<input type="text" id="prop-text" value="${element.textContent.trim()}">
|
||||
`;
|
||||
// Assurez-vous d'avoir une méthode pour mettre à jour le texte si contenteditable n'est pas utilisé
|
||||
document.getElementById('prop-text').addEventListener('input', (e) => {
|
||||
element.textContent = e.target.value;
|
||||
});
|
||||
}
|
||||
|
||||
// 2. Contrôle de la Couleur (Exemple pour la couleur de fond)
|
||||
propertyControls.innerHTML += `
|
||||
<label for="prop-color">Couleur de fond :</label>
|
||||
<input type="color" id="prop-color" value="#ffffff">
|
||||
`;
|
||||
document.getElementById('prop-color').addEventListener('input', (e) => {
|
||||
element.style.backgroundColor = e.target.value;
|
||||
});
|
||||
|
||||
// 3. Contrôle de la Taille (Exemple pour la largeur)
|
||||
propertyControls.innerHTML += `
|
||||
<label for="prop-width">Largeur (px) :</label>
|
||||
<input type="number" id="prop-width" value="${element.offsetWidth}">
|
||||
`;
|
||||
document.getElementById('prop-width').addEventListener('input', (e) => {
|
||||
element.style.width = `${e.target.value}px`;
|
||||
});
|
||||
|
||||
// 4. Ajoutez ici des contrôles spécifiques (Ex: 'Taille Police' pour le texte, 'Border Radius' pour le bouton, etc.)
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
</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>
|
||||
<div class="properties-panel" id="properties-panel">
|
||||
<h3>Propriétés de l'Élément</h3>
|
||||
<p>Cliquez sur un élément dans la zone principale pour modifier ses propriétés.</p>
|
||||
|
||||
<div id="property-controls">
|
||||
</div>
|
||||
</div>
|
||||
<footer class="footer">
|
||||
Bandeau du bas / Pied de page
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
20
css/template.html
Normal file
20
css/template.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Template</title>
|
||||
<style>
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user