This commit is contained in:
Philippe Torrel
2026-10-09 10:54:32 +02:00
parent 19dc8aed74
commit df640e0af2
42 changed files with 528 additions and 39 deletions
@@ -79,12 +79,12 @@
// removeChild() // IE11 support
list.removeChild($('ul.list li'));
// classList
// classList - DOMTokenList
list.classList.add('list-group');
list.classList.remove('andere-klasse');
list.classList.toggle('active');
// dataset & attribute
// dataset - DOMStringMap & attribute
list.dataset.id = 'list'; // <ul data-id="list">...</ul>
list.setAttribute('aria-label', 'Hauptliste');
list.removeAttribute('aria-label');
@@ -36,6 +36,8 @@
// document.querySelectorAll('css-selector')
console.log(Array.from(document.querySelectorAll('ul.list'))); //=> [<li>Listenpunkt 01</li>, ...]
// document.body.images
// =======================
// document.getElementById('ID');
@@ -2,4 +2,5 @@ const PRODUCTS = [
{ name: '3Doodler 3D Printing Pen', price: 29.99 },
{ name: 'Powerstation 5- E. Maximus Chargus', price: 44.95 },
{ name: '8-Bit Legendary Hero Heat-Change Mug', price: 6.99 },
{ name: '16-Bit Legendary Hero Heat-Change Mug', price: 12.99 },
];
@@ -1,5 +1,6 @@
[
{ "name": "3Doodler 3D Printing Pen", "price": 29.99 },
{ "name": "Powerstation 5- E. Maximus Chargus", "price": 44.95 },
{ "name": "8-Bit Legendary Hero Heat-Change Mug", "price": 6.99 }
{ "name": "8-Bit Legendary Hero Heat-Change Mug", "price": 6.99 },
{ "name": "16-Bit Legendary Hero Heat-Change Mug", "price": 12.99 }
]
@@ -25,6 +25,7 @@
<th class="th-actions">Actions</th>
</tr>
</thead>
<!-- products via js -->
<tbody></tbody>
<tfoot>
<tr>
@@ -154,6 +154,7 @@ const ProductManager = (el = null, options = {}) => {
return {
element: DOM.module,
init,
initProducts,
};
};
@@ -37,7 +37,7 @@
<hr />
<div class="box" id="source-box"></div>
<div class="target-box"></div>
<div class="target-box" ondra></div>
</div>
</main>
<script>
@@ -0,0 +1,27 @@
const CreateBtn = (options = {}) => {
const {
classNames = ['btn-primary'],
iconName = 'circle',
label,
clickHandler = (e) => {
console.log('no click action');
},
} = options;
const btn = document.createElement('button');
const icon = document.createElement('i');
const span = document.createElement('span');
btn.classList.add('btn', ...classNames);
icon.classList.add('fas', `fa-${iconName}`);
span.classList.add('visually-hidden');
span.textContent = label;
btn.addEventListener('click', clickHandler);
btn.appendChild(icon);
btn.appendChild(span);
return btn;
};
export default CreateBtn;
@@ -18,17 +18,28 @@ const ProductManager = (el = null, options = {}) => {
templateRow: module.querySelector('.template-row'),
};
console.log(DOM);
// console.log(DOM);
// === INIT =============
const init = () => {
// Funktionsaufrufe zu beginn der Anwendung
initProducts();
DOM.btnAdd.disabled = true;
// Event-Lauscher zu beginn der Anwendung
DOM.btnAdd.addEventListener('click', onClickAdd);
window.addEventListener('keyup', onKeyUp);
};
// === EVENTHANDLER =====
const onKeyUp = (e) => {
DOM.btnAdd.disabled = !(DOM.inputName.value !== '' && DOM.inputPrice.value !== '');
// if (DOM.inputName.value !== '' && DOM.inputPrice.value !== '') {
// DOM.btnAdd.disabled = false;
// } else {
// DOM.btnAdd.disabled = true;
// }
};
const onClickAdd = (e) => {
const product = {
name: DOM.inputName.value, //
@@ -36,6 +47,8 @@ const ProductManager = (el = null, options = {}) => {
};
addProduct(product);
DOM.inputName.value = DOM.inputPrice.value = '';
DOM.btnAdd.disabled = true;
disableNonFunctionalButtons();
};
@@ -51,14 +64,62 @@ const ProductManager = (el = null, options = {}) => {
const onClickMoveUp = (e) => {
const btn = e.currentTarget;
const currentRow = parents(btn, 'tr')[0];
DOM.tbody.insertBefore(currentRow, currentRow.previousElementSibling);
currentRow.previousElementSibling.before(currentRow);
// DOM.tbody.insertBefore(currentRow, currentRow.previousElementSibling);
disableNonFunctionalButtons();
};
const onClickMoveDown = (e) => {
const btn = e.currentTarget;
const currentRow = parents(btn, 'tr')[0];
DOM.tbody.insertBefore(currentRow, currentRow.nextElementSibling.nextElementSibling);
currentRow.nextElementSibling.after(currentRow);
// DOM.tbody.insertBefore(currentRow, currentRow.nextElementSibling.nextElementSibling);
disableNonFunctionalButtons();
};
const onMouseDownDrag = (e) => {
const btn = e.currentTarget;
const currentRow = parents(btn, 'tr')[0]; // btn.closest('tr'); // btn.parentNode.parentNode;
currentRow.draggable = true; // => <tr draggable="true" >...</tr>
};
const onMouseUpDrag = (e) => {
const btn = e.currentTarget;
const currentRow = parents(btn, 'tr')[0]; // btn.closest('tr'); // btn.parentNode.parentNode;
currentRow.draggable = false; // => <tr draggable="false" >...</tr>
};
const onDragStart = (e) => {
// console.log('DragEvent: ', e);
const currentRow = e.currentTarget;
const idx = [...currentRow.parentNode.children].indexOf(currentRow);
e.dataTransfer.setData('text/plain', String(idx));
// console.log('tr reference index: ', idx);
};
const onDragOver = (e) => {
e.preventDefault(); // WICHTIG: sonst funktioniet drop-EventHandler nicht
};
const onDrop = (e) => {
const currentRow = e.currentTarget; // <- Zielzeile, aud die gedroppt wird
const targetIdx = [...currentRow.parentNode.children].indexOf(currentRow);
const sourceIdx = Number(e.dataTransfer.getData('text/plain'));
console.log({ targetIdx, sourceIdx });
//const draggedRow = DOM.tbody.querySelector(`tr:nth-child(${sourceIdx + 1})`);
const draggedRow = DOM.tbody.children[sourceIdx];
// Guard wenn Element auf sich selbst losgelassen wurde, abbruch
if (sourceIdx === targetIdx) return;
// Verschiebe das Element im DOM
if (sourceIdx > targetIdx) {
currentRow.before(draggedRow);
} else {
currentRow.after(draggedRow);
}
disableNonFunctionalButtons();
};
@@ -99,7 +160,13 @@ const ProductManager = (el = null, options = {}) => {
const btnMoveUpEl = trEl.querySelector('.button-product-move-up');
const btnMoveDownEl = trEl.querySelector('.button-product-move-down');
// TODO: Optional Drag 'n Drop hinzufügen.
// Drag 'n Drop hinzufügen.
btnDragEl.addEventListener('mousedown', onMouseDownDrag);
btnDragEl.addEventListener('mouseup', onMouseUpDrag);
trEl.addEventListener('dragstart', onDragStart);
trEl.addEventListener('dragover', onDragOver);
trEl.addEventListener('drop', onDrop);
tdNameEl.textContent = name;
tdPriceEl.textContent = Number(price).toFixed(2);
@@ -110,32 +177,6 @@ const ProductManager = (el = null, options = {}) => {
DOM.tbody.appendChild(trEl);
};
// const createBtn = (options = {}) => {
// const {
// classNames = ['btn-primary'],
// iconName = 'circle',
// label,
// clickHandler = (e) => {
// console.log('no click action');
// },
// } = options;
// const btn = document.createElement('button');
// const icon = document.createElement('i');
// const span = document.createElement('span');
// btn.classList.add('btn', ...classNames);
// icon.classList.add('fas', `fa-${iconName}`);
// span.classList.add('visually-hidden');
// span.textContent = label;
// btn.addEventListener('click', clickHandler);
// btn.appendChild(icon);
// btn.appendChild(span);
// return btn;
// };
const disableNonFunctionalButtons = () => {
DOM.tbody.querySelectorAll('tr').forEach((tr) => {
tr.querySelector('.button-product-move-up').disabled = !tr.previousElementSibling;
@@ -1,5 +1,7 @@
[
{ "name": "3Doodler 3D Printing Pen", "price": 29.99 },
{ "name": "Powerstation 5- E. Maximus Chargus", "price": 44.95 },
{ "name": "8-Bit Legendary Hero Heat-Change Mug", "price": 6.99 }
{ "name": "8-Bit Legendary Hero Heat-Change Mug", "price": 6.99 },
{ "name": "16-Bit Legendary Hero Heat-Change Mug", "price": 12.99 },
{ "name": "32-Bit Legendary Hero Heat-Change Mug", "price": 14.99 }
]
@@ -1,5 +1,5 @@
{
"name": "product-manager-tpl-json",
"name": "product-manager-final",
"version": "1.0.0",
"description": "",
"main": "index.js",