This commit is contained in:
21
webseite-sass-js/dev/scripts/main.js
Normal file
21
webseite-sass-js/dev/scripts/main.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import ProductManager from './modules/ProductManager'; // Dateiendung kann weggelassen werden, wenn ein Bundler eingesetzt wird (esbuild, webpack, rollup, etc.)
|
||||
|
||||
(() => {
|
||||
// === DOM & VARS =======
|
||||
const DOM = {};
|
||||
|
||||
// === INIT =============
|
||||
const init = () => {
|
||||
// TODO: routing
|
||||
const pm = ProductManager();
|
||||
console.log('init');
|
||||
};
|
||||
|
||||
// === EVENTHANDLER =====
|
||||
|
||||
// === XHR/FETCH ========
|
||||
|
||||
// === FUNCTIONS ========
|
||||
|
||||
init();
|
||||
})();
|
||||
231
webseite-sass-js/dev/scripts/modules/ProductManager.js
Normal file
231
webseite-sass-js/dev/scripts/modules/ProductManager.js
Normal file
@@ -0,0 +1,231 @@
|
||||
// Factory Function
|
||||
const ProductManager = (el = null) => {
|
||||
// === DOM & VARS =======
|
||||
|
||||
const module = el || document.querySelector('.product-manager') || console.error('Product Manager not found');
|
||||
|
||||
if (!module) return;
|
||||
|
||||
const DOM = {
|
||||
module,
|
||||
table: module.querySelector('.table-products'),
|
||||
tBody: module.querySelector('tbody'),
|
||||
inputName: module.querySelector('.input-product-name'),
|
||||
inputPrice: module.querySelector('.input-product-price'),
|
||||
btnAdd: module.querySelector('.button-product-add'),
|
||||
templateRow: module.querySelector('.template-row'),
|
||||
};
|
||||
|
||||
console.log(DOM);
|
||||
|
||||
// === INIT =============
|
||||
const init = () => {
|
||||
console.log('init');
|
||||
// Funktionaufrufe zu beginn der Anwendung
|
||||
initProducts();
|
||||
|
||||
// Event-Lauscher zu beginn der Anwendung
|
||||
DOM.btnAdd.addEventListener('click', onClickAdd);
|
||||
};
|
||||
|
||||
// === EVENTHANDLER =====
|
||||
const onClickAdd = (e) => {
|
||||
console.log('click');
|
||||
|
||||
const product = {
|
||||
name: DOM.inputName.value,
|
||||
price: Number(DOM.inputPrice.value),
|
||||
};
|
||||
|
||||
addProduct(product);
|
||||
|
||||
disableNonFunctionalButtons();
|
||||
};
|
||||
|
||||
const onClickRemove = (e) => {
|
||||
const btnEl = e.currentTarget;
|
||||
//const currentRowEl = btnEl.parentNode.parentNode; // parentNode -> td - parentNode -> tr
|
||||
// MDN https://developer.mozilla.org/de/docs/Web/API/Element/closest
|
||||
//const currentRowEl = btnEl.closest('tr');
|
||||
|
||||
const currentRowEl = parents(btnEl, 'tr')[0];
|
||||
|
||||
currentRowEl.remove(); // kein IE11 support
|
||||
// DOM.tBody.removeChild(currentRowEl);
|
||||
disableNonFunctionalButtons();
|
||||
};
|
||||
|
||||
const onClickMoveUp = (e) => {
|
||||
const btnEl = e.currentTarget;
|
||||
// const currentRowEl = btnEl.parentNode.parentNode; // aktuelle Zeile (tr) mit dem Button
|
||||
const currentRowEl = parents(btnEl, 'tr')[0];
|
||||
|
||||
// ParentNode.insertBefore(referenceElement, targetElement)
|
||||
// DOM.tBody.insertBefore(currentRowEl, currentRowEl.previousElementSibling);
|
||||
|
||||
// targetElement.before(referenceElement)
|
||||
currentRowEl.previousElementSibling.before(currentRowEl);
|
||||
|
||||
console.log('move up');
|
||||
disableNonFunctionalButtons();
|
||||
};
|
||||
|
||||
const onClickMoveDown = (e) => {
|
||||
const btnEl = e.currentTarget;
|
||||
// const currentRowEl = btnEl.parentNode.parentNode; // aktuelle Zeile (tr) mit dem Button
|
||||
const currentRowEl = parents(btnEl, 'tr')[0];
|
||||
|
||||
// ParentNode.insertBefore(referenceElement, targetElement)
|
||||
// DOM.tBody.insertBefore(currentRowEl, currentRowEl.nextElementSibling.nextElementSibling);
|
||||
|
||||
// targetElement.after(referenceElement)
|
||||
currentRowEl.nextElementSibling.after(currentRowEl);
|
||||
|
||||
console.log('move down');
|
||||
disableNonFunctionalButtons();
|
||||
};
|
||||
|
||||
// Drag 'n Drop EventHandler
|
||||
const onMouseDownDrag = (e) => {
|
||||
const btnEl = e.currentTarget;
|
||||
const currentRowEl = parents(btnEl, 'tr')[0];
|
||||
currentRowEl.draggable = true;
|
||||
};
|
||||
const onMouseUpDrag = (e) => {
|
||||
const btnEl = e.currentTarget;
|
||||
const currentRowEl = parents(btnEl, 'tr')[0];
|
||||
currentRowEl.draggable = false;
|
||||
};
|
||||
|
||||
const onDragStart = (e) => {
|
||||
console.log('DragEvent: ', e);
|
||||
const currentRowEl = e.currentTarget; // tr <- aktuelle Zeie, die bewegt wird
|
||||
const idx = [...currentRowEl.parentNode.children].indexOf(currentRowEl);
|
||||
|
||||
e.dataTransfer.setData('text/plain', idx); // e.dataTransfer.setData('application/json', JSON.stringify({idx, name: sourceElement}));
|
||||
console.log('tr index:', idx);
|
||||
};
|
||||
|
||||
const onDragOver = (e) => {
|
||||
e.preventDefault(); // WICHTIG! Sonst funktioniert drop EventHandler nicht.
|
||||
};
|
||||
|
||||
const onDrop = (e) => {
|
||||
const currentRowEl = e.currentTarget; // tr <- Zielezeile, auf die gedroppt wird.
|
||||
const targetIdx = [...currentRowEl.parentNode.children].indexOf(currentRowEl);
|
||||
const sourceIdx = parseInt(e.dataTransfer.getData('text/plain'));
|
||||
// const { sourceIdx } = JSON.parse(e.dataTransfer.getData('application/json'));
|
||||
|
||||
console.log({ targetIdx, sourceIdx });
|
||||
|
||||
// Guard wenn Element auf sich selbst losgelassen wurde, abbruch
|
||||
if (sourceIdx === targetIdx) {
|
||||
return;
|
||||
}
|
||||
|
||||
const draggedEl = DOM.tBody.querySelector(`tr:nth-child(${sourceIdx + 1})`);
|
||||
|
||||
// Verschiebe das Element im DOM
|
||||
if (sourceIdx > targetIdx) {
|
||||
currentRowEl.before(draggedEl);
|
||||
} else {
|
||||
currentRowEl.after(draggedEl);
|
||||
}
|
||||
|
||||
disableNonFunctionalButtons();
|
||||
};
|
||||
|
||||
// === XHR/FETCH ========
|
||||
const fetchProducts = async () => {
|
||||
try {
|
||||
const response = await fetch('/data/products.json'); // HTTP Request URL
|
||||
if (!response.ok) {
|
||||
throw new Error('Fetch went wrong.');
|
||||
}
|
||||
const data = await response.json(); // HTTP-Response
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
// === FUNCTIONS ========
|
||||
|
||||
const initProducts = () => {
|
||||
fetchProducts().then((products) => {
|
||||
products.forEach((product) => {
|
||||
addProduct(product);
|
||||
});
|
||||
disableNonFunctionalButtons();
|
||||
});
|
||||
|
||||
// PRODUCTS.forEach((product) => {
|
||||
// addProduct(product);
|
||||
// });
|
||||
//disableNonFunctionalButtons();
|
||||
// PRODUCTS.forEach(addProduct);
|
||||
};
|
||||
|
||||
const addProduct = (product) => {
|
||||
const { name, price } = product;
|
||||
|
||||
// https://developer.mozilla.org/de/docs/Web/API/HTMLTemplateElement/content
|
||||
const trEl = DOM.templateRow.content.firstElementChild.cloneNode(true);
|
||||
|
||||
const tdNameEl = trEl.querySelector('.td-name');
|
||||
const tdPriceEl = trEl.querySelector('.td-price');
|
||||
const btnRemoveEl = trEl.querySelector('.button-product-remove');
|
||||
const btnMoveUpEl = trEl.querySelector('.button-product-move-up');
|
||||
const btnMoveDownEl = trEl.querySelector('.button-product-move-down');
|
||||
|
||||
const btnDragEl = trEl.querySelector('.button-drag');
|
||||
|
||||
tdNameEl.textContent = name;
|
||||
tdPriceEl.textContent = price;
|
||||
|
||||
btnRemoveEl.addEventListener('click', onClickRemove);
|
||||
btnMoveUpEl.addEventListener('click', onClickMoveUp);
|
||||
btnMoveDownEl.addEventListener('click', onClickMoveDown);
|
||||
|
||||
// Drag 'n Drop Events
|
||||
btnDragEl.addEventListener('mousedown', onMouseDownDrag);
|
||||
btnDragEl.addEventListener('mouseup', onMouseUpDrag);
|
||||
|
||||
trEl.addEventListener('dragstart', onDragStart);
|
||||
trEl.addEventListener('dragover', onDragOver);
|
||||
trEl.addEventListener('drop', onDrop);
|
||||
|
||||
DOM.tBody.appendChild(trEl); // Im DOM hinzufügen
|
||||
};
|
||||
|
||||
const disableNonFunctionalButtons = () => {
|
||||
Array.from(DOM.tBody.querySelectorAll('tr')).forEach((tr) => {
|
||||
const btnMoveUp = tr.querySelector('.button-product-move-up');
|
||||
const btnMoveDown = tr.querySelector('.button-product-move-down');
|
||||
|
||||
btnMoveUp.disabled = !tr.previousElementSibling;
|
||||
btnMoveDown.disabled = !tr.nextElementSibling;
|
||||
});
|
||||
};
|
||||
|
||||
// Helferfunktion aus jQuery (youmightnotjquery)
|
||||
const parents = (el, selector) => {
|
||||
const parents = [];
|
||||
while ((el = el.parentNode) && el !== document) {
|
||||
if (!selector || el.matches(selector)) parents.push(el);
|
||||
}
|
||||
return parents;
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
return {
|
||||
init,
|
||||
initProducts,
|
||||
};
|
||||
};
|
||||
|
||||
// Freigabe für import
|
||||
export default ProductManager;
|
||||
Reference in New Issue
Block a user