finalized JS DOM

This commit is contained in:
Philippe Torrel
2026-07-20 12:57:48 +02:00
parent 0a69891333
commit 549c2ac243
32 changed files with 772 additions and 42 deletions

View File

@@ -23,6 +23,7 @@
console.log('init');
// Funktionaufrufe zu beginn der Anwendung
initProducts();
// Event-Lauscher zu beginn der Anwendung
DOM.btnAdd.addEventListener('click', onClickAdd);
};
@@ -37,33 +38,51 @@
};
addProduct(product);
disableNonFunctionalButtons();
};
const onClickRemove = (e) => {
const btnEl = e.currentTarget;
const currentRowEl = btnEl.parentNode.parentNode; // parentNode -> td - parentNode -> tr
//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 = 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);
// 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 = 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);
// DOM.tBody.insertBefore(currentRowEl, currentRowEl.nextElementSibling.nextElementSibling);
// targetElement.after(referenceElement)
currentRowEl.nextElementSibling.after(currentRowEl);
console.log('move down');
disableNonFunctionalButtons();
};
// === XHR/FETCH ========
@@ -73,7 +92,7 @@
PRODUCTS.forEach((product) => {
addProduct(product);
});
disableNonFunctionalButtons();
// PRODUCTS.forEach(addProduct);
};
@@ -93,29 +112,65 @@
const td = document.createElement('td');
td.classList.add('td-actions');
const btnRemove = createButtonRemove();
const btnMoveUp = createButtonMoveUp();
const btnMoveDown = createButtonMoveDown();
const btnRemove = createButton({
classes: ['btn-danger', 'button-product-remove'],
iconName: 'trash-can',
label: 'Remove Product',
clickHandler: onClickRemove,
});
const btnMoveUp = createButton({
classes: ['btn-secondary', 'button-product-move-up'],
iconName: 'caret-up',
label: 'Move Up',
clickHandler: onClickMoveUp,
});
const btnMoveDown = createButton({
classes: ['btn-secondary', 'button-product-move-down'],
iconName: 'caret-down',
label: 'Move Down',
clickHandler: onClickMoveDown,
});
// td.append(btnRemove, btnMoveUp, btnMoveDown)
td.appendChild(btnRemove);
td.appendChild(btnMoveUp);
td.appendChild(btnMoveDown);
// td.appendChild(
// createButton({
// classes: ['btn-primary', 'button-login'],
// label: 'login',
// iconName: 'right-to-bracket',
// clickHandler: () => {
// console.log('login');
// },
// }),
// );
return td;
};
const createButtonRemove = () => {
const createButton = (options = {}) => {
// Destructuring
const {
classes = [],
iconName = 'circle',
label = 'No Label',
clickHandler = () => {
console.log('no action');
},
} = options;
const btn = document.createElement('button');
const icon = document.createElement('i');
const span = document.createElement('span');
btn.classList.add('btn', 'btn-sm', 'btn-danger', 'button-product-remove');
icon.classList.add('fas', 'fa-trash-can');
btn.classList.add('btn', 'btn-sm', ...classes);
icon.classList.add('fas', `fa-${iconName}`);
span.classList.add('visually-hidden');
span.textContent = 'Remove Product';
span.textContent = label;
btn.addEventListener('click', onClickRemove);
btn.addEventListener('click', clickHandler);
// btn.append(icon,span)
btn.appendChild(icon);
btn.appendChild(span);
@@ -123,41 +178,68 @@
return btn;
};
const createButtonMoveUp = () => {
const btn = document.createElement('button');
const icon = document.createElement('i');
const span = document.createElement('span');
// createButton({
// classes: ['btn-primary', 'button-login-user'],
// iconName: 'right-to-bracket',
// label: 'Login',
// clickHandler: () => {
// console.log('login process...');
// },
// });
btn.classList.add('btn', 'btn-sm', 'btn-secondary', 'button-product-move-up');
icon.classList.add('fas', 'fa-caret-up');
span.classList.add('visually-hidden');
span.textContent = 'Move Up';
// const createButtonRemove = () => {
// const btn = document.createElement('button');
// const icon = document.createElement('i');
// const span = document.createElement('span');
btn.addEventListener('click', onClickMoveUp);
// btn.append(icon,span)
btn.appendChild(icon);
btn.appendChild(span);
// btn.classList.add('btn', 'btn-sm', 'btn-danger', 'button-product-remove');
// icon.classList.add('fas', 'fa-trash-can');
// span.classList.add('visually-hidden');
// span.textContent = 'Remove Product';
return btn;
};
// btn.addEventListener('click', onClickRemove);
// // btn.append(icon,span)
// btn.appendChild(icon);
// btn.appendChild(span);
const createButtonMoveDown = () => {
const btn = document.createElement('button');
const icon = document.createElement('i');
const span = document.createElement('span');
// return btn;
// };
btn.classList.add('btn', 'btn-sm', 'btn-secondary', 'button-product-move-down');
icon.classList.add('fas', 'fa-caret-down');
span.classList.add('visually-hidden');
span.textContent = 'Move Down';
// const createButtonMoveUp = () => {
// const btn = document.createElement('button');
// const icon = document.createElement('i');
// const span = document.createElement('span');
btn.addEventListener('click', onClickMoveDown);
// btn.append(icon,span)
btn.appendChild(icon);
btn.appendChild(span);
// btn.classList.add('btn', 'btn-sm', 'btn-secondary', 'button-product-move-up');
// icon.classList.add('fas', 'fa-caret-up');
// span.classList.add('visually-hidden');
// span.textContent = 'Move Up';
return btn;
};
// btn.addEventListener('click', onClickMoveUp);
// // btn.append(icon,span)
// btn.appendChild(icon);
// btn.appendChild(span);
// return btn;
// };
// const createButtonMoveDown = () => {
// const btn = document.createElement('button');
// const icon = document.createElement('i');
// const span = document.createElement('span');
// btn.classList.add('btn', 'btn-sm', 'btn-secondary', 'button-product-move-down');
// icon.classList.add('fas', 'fa-caret-down');
// span.classList.add('visually-hidden');
// span.textContent = 'Move Down';
// btn.addEventListener('click', onClickMoveDown);
// // btn.append(icon,span)
// btn.appendChild(icon);
// btn.appendChild(span);
// return btn;
// };
const createTd = (text, className = '') => {
const td = document.createElement('td');
@@ -177,5 +259,24 @@
return tr;
};
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();
})();

View File

@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DOM Creation</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<h1>DOM Creation</h1>
<hr />
<ul class="list">
<li>Listenpunkt 01</li>
<li>Listenpunkt 02</li>
<li>Listenpunkt 03</li>
<li>Listenpunkt 04</li>
</ul>
</div>
</main>
<script>
'use strict';
const $ = (qs) => document.querySelector(qs);
const $$ = (qs) => Array.from(document.querySelectorAll(qs));
// Node.innerHTML
$('ul.list').innerHTML += '<li>Listenpunkt 05</li>';
// Node.innerText & Node.textContent
$('ul.list li').textContent = 'Listenpunkt 001';
$('ul.list li:nth-child(2)').innerText = 'Listenpunkt 002';
// document.createElement('HTML_ELEMENT')
const liEl = document.createElement('li');
liEl.textContent = 'Listenpunkt 06';
// Node.cloneNode(true)
const liCloneEl = $('ul.list li').cloneNode(true);
// DOM Manipulation ==========
$('ul.list').appendChild(liEl);
$('ul.list').appendChild(liCloneEl);
</script>
</body>
</html>

View File

@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DOM Manipulation</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<h1>DOM Manipulation</h1>
<hr />
<ul class="list">
<li>Listenpunkt 01</li>
<li>Listenpunkt 02</li>
<li>Listenpunkt 03</li>
<li>Listenpunkt 04</li>
</ul>
</div>
</main>
<script>
'use strict';
const $ = (qs) => document.querySelector(qs);
const $$ = (qs) => Array.from(document.querySelectorAll(qs));
const liEl = document.createElement('li');
liEl.textContent = 'Listenpunkt neu';
// DOM Manipulation
// appendChild()
$('ul.list').appendChild(liEl);
// append()
$('ul.list').append($('ul.list li'));
// prepend()
$('ul.list').prepend(liEl);
// remove()
$('ul.list li').remove();
// removeChild() // IE11 support
$('ul.list').removeChild($('ul.list li'));
// insertBefore(refNode, targetNode)
$('ul.list').insertBefore($('ul.list li'), $('ul.list li:last-child'));
// before() || after()
$('ul.list li').before($('ul.list li:last-child'));
$('ul.list li:first-child').after($('ul.list li:last-child'));
//
$('ul.list').classList.add('list-group');
$('ul.list').dataset.id = 'list';
$('.container').id = 'main-container';
$('h1').style.backgroundColor = 'tomato';
$('h1').setAttribute('title', 'headline');
</script>
</body>
</html>

View File

@@ -0,0 +1,53 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DOM Selection</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<h1 id="headline">DOM Selection</h1>
<hr />
<!-- ul.list>li*4{Listenpunkt 0$} -->
<ul class="list">
<li>Listenpunkt 01</li>
<li>Listenpunkt 02</li>
<li>Listenpunkt 03</li>
<li>Listenpunkt 04</li>
</ul>
</div>
</main>
<script>
'use strict';
const $ = (qs) => document.querySelector(qs);
const $$ = (qs) => Array.from(document.querySelectorAll(qs));
// DOM Selection
console.log($('ul.list li')); //=> <li>Listenpunkt 01</li>
console.log($$('ul.list li')); //=> [<li>Listenpunkt 01</li>, ...]
// document.querySelector('css-selector')
console.log(document.querySelector('ul.list li')); //=> <li>Listenpunkt 01</li>
// document.querySelectorAll('css-selector')
console.log(Array.from(document.querySelectorAll('ul.list'))); //=> [<li>Listenpunkt 01</li>, ...]
// =======================
// document.getElementById('ID');
console.log(document.getElementById('headline')); //=> <h1 id="headline">DOM Selection</h1>
// ===== NOT RECOMMENDED TO USE OLD SELECT METHODS =====
// document.getElementsByClassName('className')
console.log(document.getElementsByClassName('container')); //=> HTMLCollection [div.container.py-5]
// document.getElementsByTagName('li')
console.log(document.getElementsByTagName('li')); //=> HTMLCollection(4) [li, li, li, li]
</script>
</body>
</html>

View File

@@ -0,0 +1,65 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DOM Traversal</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<h1>DOM Traversal</h1>
<hr />
<!-- ul.list>li*4{Listenpunkt 0$} -->
<ul class="list">
<li>Listenpunkt 01</li>
<li>Listenpunkt 02</li>
<li>Listenpunkt 03</li>
<li>Listenpunkt 04</li>
</ul>
</div>
</main>
<script>
'use strict';
const $ = (qs) => document.querySelector(qs);
const $$ = (qs) => Array.from(document.querySelectorAll(qs));
// DOM Traversal
const firstLiEl = $('ul.list li');
// parentNode - Elternelement
console.log(firstLiEl.parentNode); //=> <ul class="list">...</ul>
// previousElementSibling - Geschwisterelement (vor)
console.log($('ul.list li:last-child').previousElementSibling); //=> <li>Listenpunkt 03</li>
// nextElementSibling - Geschwisterelement (nach)
console.log($('ul.list li:first-child').nextElementSibling); //=> <li>Listenpunkt 02</li>
// children - Kindelemente
console.log($('ul.list').children); // => HTMLCollection [li, li, li, li]
// Array.from(Node.children)
console.log(Array.from($('ul.list').children)); // => [li, li, li, li]
// firstElementChild - erstes Kindelement
console.log($('ul.list').firstElementChild); //=> <li>Listenpunkt 01</li>
// lastElementChild - letztes Kindelement
console.log($('ul.list').lastElementChild); //=> <li>Listenpunkt 04</li>
// ==========
console.log($('ul.list').children[1]); //=> <li>Listenpunkt 02</li>
// childElementCount
console.log($('ul.list').childElementCount); //=> 4
console.log($('ul.list').children.length); //=> 4
console.log($$('ul.list > li').length); //=> 4
console.log($('ul.list').querySelectorAll('li').length); //=> 4
</script>
</body>
</html>

View File

@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>textContent vs innerText vs innerHTML</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<h1>textContent vs innerText vs innerHTML</h1>
<hr />
<p>
Lorem ipsum dolor sit, <a href="https://www.gfn.de">GFN Link</a> amet consectetur adipisicing elit. Amet
tempora repudiandae dicta et libero, ex, quibusdam nisi id atque quaerat nam asperiores laborum hic ipsum
suscipit numquam. Obcaecati vero consequatur repellendus nostrum beatae laborum voluptate aperiam numquam
<span style="display: none">
VERSTECKT!!!! Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, commodi.
</span>
iusto optio delectus animi quia quam, provident vitae ex. Accusantium, officiis? Nemo quidem accusantium
voluptatibus cumque voluptates natus, consequatur exercitationem eum eligendi dolor sit nisi. Magni enim omnis
voluptatibus obcaecati aut? Nulla asperiores incidunt atque labore alias quia assumenda molestias, dolores
facilis aspernatur ea quos! Magnam suscipit et, saepe culpa repellat nesciunt repudiandae dignissimos? Nemo
neque nisi repellendus doloribus reiciendis, ducimus quae id?
</p>
<div class="output-text-content alert alert-secondary my-3"></div>
<div class="output-inner-text alert alert-secondary my-3"></div>
<div class="output-inner-html alert alert-secondary my-3"></div>
</div>
</main>
<script>
'use strict';
const $ = (qs) => document.querySelector(qs);
const $$ = (qs) => Array.from(document.querySelectorAll(qs));
// textContent ohne Leeraum (am Anfang und Ende) und ohne HTML-Syntax (<TAGNAME>...</TAGNAME>)
console.log('textContent:', $('p').textContent.length);
// innerText ohne Leeraum (am Anfang, Ende und Zeilenumbrüchen), ohne HTML-Syntax (<TAGNAME>...</TAGNAME>) und ohne versteckten Inhalt
console.log('innerText:', $('p').innerText.length);
// innerHTML so wie im Element vorliegend
console.log('innerHTML:', $('p').innerHTML.length);
$('.output-text-content').textContent =
'<p>lorem ipsum <a href="#">Link</a><span style="display:none">IM SPAN</span></p>';
$('.output-inner-text').innerText =
'<p>lorem ipsum <a href="#">Link</a><span style="display:none">IM SPAN</span></p>';
$('.output-inner-html').innerHTML =
'<p>lorem ipsum <a href="#">Link</a><span style="display:none">IM SPAN</span></p>';
</script>
</body>
</html>

View File

@@ -0,0 +1,26 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Node.outerHTML vs Node.innerHTML</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<h1>Node.outerHTML vs <em>Node.innerHTML</em></h1>
</div>
</main>
<script>
'use strict';
const $ = (qs) => document.querySelector(qs);
const $$ = (qs) => Array.from(document.querySelectorAll(qs));
console.log($('h1').innerHTML); //=> Node.innerHTML <em>Node.innerHTML</em>
console.log($('h1').outerHTML); //=> <h1>Node.outerHTML vs <em>Node.innerHTML</em></h1>
</script>
</body>
</html>