This commit is contained in:
Philippe Torrel
2026-10-07 09:55:58 +02:00
parent 7763aa89dc
commit 723c95a3f9
22 changed files with 504 additions and 12 deletions
@@ -0,0 +1,4 @@
.light-bulbs{
padding: 1rem;
border: 2px solid #555;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

@@ -0,0 +1,92 @@
// Helper DOM Selektion mit $ & $$
const $ = (qs) => document.querySelector(qs);
const $$ = (qs) => Array.from(document.querySelectorAll(qs));
Node.prototype.on = function(name, fn) {
this.addEventListener(name, fn);
return this;
};
// // anstatt
// document.querySelector('button').addEventListener('click', (event) => { });
// // wird zu:
// document.querySelector('button').on('click', (event) => { });
Array.prototype.on = Array.prototype.addEventListener = function(name, fn) {
this.forEach((elem) => elem.on(name, fn));
return this;
};
// anstatt
// Array.from(document.querySelectorAll('.menu-main li a')).forEach((elem) =>
// elem.addEventListener('click', (event) => {
// console.log(event);
// })
// );
// // wird zu
// Array.from(document.querySelectorAll('.menu-main li a')).on(
// 'click',
// (event) => {
// console.log(event);
// }
// );
// helper
const $on = (el, ev, fn) => {
Array.isArray(el) ? el.forEach(ae => $on(ae, ev, fn)) :
el.addEventListener(ev, fn);
return el;
};
// times - funktion
function times(n, fn) {
const result = Array(n);
for (let i = 0; i < n; i++) {
result[i] = fn(i);
}
return result;
}
// oder von lodash
function baseTimes(n, iteratee) {
var index = -1,
result = Array(n);
while (++index < n) {
result[index] = iteratee(index);
}
return result;
}
/*
* range(zahl bis wohin array befüllt werden soll) : array
* - array von 0 bis
parameterzahl (nicht inklusive)
*
* range(anfangswert, endwert) : array
* - array von anfangswert bis endwert (nicht inklusive)
*
* range(nfangswert, endwert, übersprungswert) : : array
* - array von anfangswert bis endwert (nicht inklusive), zwischenwerte durch übersprungswert entfallen
*/
function rangeFromStartToEnd(start, end, step = 1) {
const length = Math.max(Math.ceil((end - start) / step), 0);
const result = new Array(length);
const sign = step / Math.abs(step);
let index = 0;
for (let value = start; value * sign < end * sign; value += step) {
result[index++] = value;
}
return result;
};
function range(startOrEnd, end, step) {
if (end) {
return rangeFromStartToEnd(startOrEnd, end, step);
} else {
return rangeFromStartToEnd(0, startOrEnd);
}
};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,47 @@
'use strict';
(() => {
// === DOM & VARS =======
const DOM = {
lightGroups: Array.from(document.querySelectorAll('.light-bulbs')),
};
console.log(DOM);
const LIGHT_PATH_ON = 'assets/img/light_on.png';
const LIGHT_PATH_OFF = 'assets/img/light_off.png';
// === INIT =============
const init = () => {
DOM.lightGroups.forEach(initRunningLight);
};
// === EVENTHANDLER =====
// === XHR/FETCH ========
// === FUNCTIONS ========
const initRunningLight = (group) => {
const bulbs = Array.from(group.querySelectorAll('img'));
console.log(bulbs);
const eventType = group.dataset.event; //=> 'mouseenter' | 'click'
let activeIndex = 0;
// Jede Reihe startet mit genau einer leuchtenden Birne.
bulbs.forEach((bulb, index) => {
bulb.src = index === activeIndex ? LIGHT_PATH_ON : LIGHT_PATH_OFF;
bulb.addEventListener(eventType, () => {
// Beim Jagen reagiert nur die gerade leuchtende Birne.
if (eventType === 'mouseenter' && index !== activeIndex) return;
bulbs[activeIndex].src = LIGHT_PATH_OFF;
// Modulo sorgt nach der letzten Birne für den Sprung zum Anfang.
activeIndex = (activeIndex + 1) % bulbs.length;
bulbs[activeIndex].src = LIGHT_PATH_ON;
});
});
};
init();
})();
@@ -0,0 +1,45 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 10 - Chasing Lights</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="assets/css/main.css" />
<script src="assets/js/main.js" defer></script>
</head>
<body>
<div class="container py-5">
<div class="alert alert-primary">
<h2>Übung 10 - Chasing Lights</h2>
<p>
Eine erste Variante sind die chasing Lights. Dabei muss der Anwender das Lauflicht mit der Maus »jagen«. Immer
wenn der Mauszeiger sich über einer Glühbirne befindet, schaltet sich die nächste Birne ein und die aktuelle
aus. Versucht der Benutzer, mit dem Mauszeiger die leuchtende Glühbirne zu berühren, springt das Licht auf die
nächste über. Er »jagt« quasi das Lauflicht. Bei der letzten Lampe beginnt das Spiel wieder von vorn!
</p>
<p>
Programmiere ein weiteres Lauflicht. Diesmal soll das Lauflicht weiterspringen, wenn der Benutzer auf eine der
Lampen klickt. Auch hier gilt: Nach der letzten Lampe fängt das Licht wieder von vorn an zu laufen.
</p>
</div>
<h3>Mit der Maus jagen</h3>
<div class="light-bulbs" data-event="mouseenter">
<img src="assets/img/light_on.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
</div>
<h3 class="mt-4">Per Klick weiterschalten</h3>
<div class="light-bulbs" data-event="click">
<img src="assets/img/light_on.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
</div>
</div>
</body>
</html>
@@ -0,0 +1,4 @@
.light-bulbs{
padding: 1rem;
border: 2px solid #555;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

@@ -0,0 +1,92 @@
// Helper DOM Selektion mit $ & $$
const $ = (qs) => document.querySelector(qs);
const $$ = (qs) => Array.from(document.querySelectorAll(qs));
Node.prototype.on = function(name, fn) {
this.addEventListener(name, fn);
return this;
};
// // anstatt
// document.querySelector('button').addEventListener('click', (event) => { });
// // wird zu:
// document.querySelector('button').on('click', (event) => { });
Array.prototype.on = Array.prototype.addEventListener = function(name, fn) {
this.forEach((elem) => elem.on(name, fn));
return this;
};
// anstatt
// Array.from(document.querySelectorAll('.menu-main li a')).forEach((elem) =>
// elem.addEventListener('click', (event) => {
// console.log(event);
// })
// );
// // wird zu
// Array.from(document.querySelectorAll('.menu-main li a')).on(
// 'click',
// (event) => {
// console.log(event);
// }
// );
// helper
const $on = (el, ev, fn) => {
Array.isArray(el) ? el.forEach(ae => $on(ae, ev, fn)) :
el.addEventListener(ev, fn);
return el;
};
// times - funktion
function times(n, fn) {
const result = Array(n);
for (let i = 0; i < n; i++) {
result[i] = fn(i);
}
return result;
}
// oder von lodash
function baseTimes(n, iteratee) {
var index = -1,
result = Array(n);
while (++index < n) {
result[index] = iteratee(index);
}
return result;
}
/*
* range(zahl bis wohin array befüllt werden soll) : array
* - array von 0 bis
parameterzahl (nicht inklusive)
*
* range(anfangswert, endwert) : array
* - array von anfangswert bis endwert (nicht inklusive)
*
* range(nfangswert, endwert, übersprungswert) : : array
* - array von anfangswert bis endwert (nicht inklusive), zwischenwerte durch übersprungswert entfallen
*/
function rangeFromStartToEnd(start, end, step = 1) {
const length = Math.max(Math.ceil((end - start) / step), 0);
const result = new Array(length);
const sign = step / Math.abs(step);
let index = 0;
for (let value = start; value * sign < end * sign; value += step) {
result[index++] = value;
}
return result;
};
function range(startOrEnd, end, step) {
if (end) {
return rangeFromStartToEnd(startOrEnd, end, step);
} else {
return rangeFromStartToEnd(0, startOrEnd);
}
};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,58 @@
'use strict';
(() => {
// === DOM & VARS =======
const module = document.querySelector('.light-bulbs') || console.warn('no light-bulbs to select');
const DOM = {
module,
lights: module.querySelectorAll('img'),
};
const LIGHT_PATH_ON = 'assets/img/light_on.png';
const LIGHT_PATH_OFF = 'assets/img/light_off.png';
// === INIT =============
const init = () => {
DOM.lights.forEach((img) => {
img.addEventListener('mouseenter', bulbEnterVariant1b);
// img.addEventListener('click', bulbEnterVariant1b);
});
};
// === EVENTHANDLER =====
// Das ist die korrekte Antwort nach Aufgaben Text, aktuelles Licht aus, nächstest Licht an
const bulbEnterVariant1a = (e) => {
const img = e.target;
let nextImg = img.nextElementSibling;
img.src = img.src.replace('light_on', 'light_off');
if (!img.nextElementSibling) {
nextImg = DOM.lights[0];
}
nextImg.src = nextImg.src.replace('light_off', 'light_on');
};
// das ist, denke ich, die WIRKLICH korrekte version, who alle anderen Lichter ausgeschaltet werden, ansonsten ist da nicht mehr viel mit "chasen"
const bulbEnterVariant1b = (e) => {
const imgEl = e.target;
let nextImgEl = imgEl.nextElementSibling;
if (!imgEl.nextElementSibling) {
nextImgEl = DOM.lights[0];
}
DOM.lights.forEach((img) => {
img.src = img === nextImgEl ? LIGHT_PATH_ON : LIGHT_PATH_OFF;
});
};
// === XHR/FETCH ========
// === FUNCTIONS ========
init();
})();
@@ -0,0 +1,41 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 10 - Chasing Lights</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="assets/css/main.css" />
<script src="assets/js/main.js" defer></script>
</head>
<body>
<div class="container py-5">
<div class="alert alert-primary">
<h2>Übung 10 - Chasing Lights</h2>
<p>
Eine erste Variante sind die chasing Lights. Dabei muss der Anwender das Lauflicht mit der Maus »jagen«. Immer
wenn der Mauszeiger sich über einer Glühbirne befindet, schaltet sich die nächste Birne ein und die aktuelle
aus. Versucht der Benutzer, mit dem Mauszeiger die leuchtende Glühbirne zu berühren, springt das Licht auf die
nächste über. Er »jagt« quasi das Lauflicht. Bei der letzten Lampe beginnt das Spiel wieder von vorn!
</p>
<p>
Programmiere ein weiteres Lauflicht. Diesmal soll das Lauflicht weiterspringen, wenn der Benutzer auf eine der
Lampen klickt. Auch hier gilt: Nach der letzten Lampe fängt das Licht wieder von vorn an zu laufen.
</p>
</div>
<div class="light-bulbs">
<img src="assets/img/light_on.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_on.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
<img src="assets/img/light_off.png" alt="lightbulb" />
</div>
</div>
</body>
</html>
@@ -2,19 +2,56 @@
(() => {
// === DOM & VARS =======
const DOM = {};
const module = document.querySelector('.light-bulbs');
const DOM = {
module,
lightBulbs: Array.from(module.querySelectorAll('img[alt="lightbulb"]')),
};
const LIGHT_PATH_ON = 'assets/img/light_on.png';
const LIGHT_PATH_OFF = 'assets/img/light_off.png';
// console.log(DOM);
// === INIT =============
const init = () => {};
const init = () => {
setAllLightsOff();
DOM.lightBulbs.forEach((el, idx) => {
el.dataset.index = idx; // Index im HTMLImageElement ablegen (V1)
el.addEventListener('mouseenter', (e) => onMouseEnter(e, idx)); // Index als zweiten Parameter mitgeben (V2)
});
};
// === EVENTHANDLER =====
const onMouseEnter = (e, idx) => {
// const index = e.currentTarget.dataset.index;
const img = e.currentTarget;
const index = getIndexBy(img); // Index über Funktion ermitteln (V3)
// if (e.currentTarget.src.includes(LIGHT_PATH_ON)) {
const nextIndex = getNextIndex(index);
console.log(nextIndex);
setAllLightsOff();
DOM.lightBulbs[nextIndex].src = LIGHT_PATH_ON;
//
};
// === XHR/FETCH ========
// === FUNCTIONS ========
const getIndexBy = (img) => {
return DOM.lightBulbs.indexOf(img);
};
const getNextIndex = (currentIndex) => {
return currentIndex === DOM.lightBulbs.length - 1 ? 0 : currentIndex + 1;
};
const setAllLightsOff = () => {
DOM.lightBulbs.forEach((el) => {
el.src = LIGHT_PATH_OFF;
});
};
init();
})();
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
@@ -99,7 +99,9 @@
// Übung 11: — Teil 6
// Der neue Wunsch besteht darin, den Text blau (blue) zu färben. Dieses Mal darfst du keine CSS-Klassen verwenden.
$$('p').forEach((p) => {
p.style.color = 'blue';
});
// Weise allen p-Elementen mithilfe des Style-Objektes die Farbe blue zu. Du kannst dafür direkt die JavaScript-Konsole verwenden.
}
</script>
@@ -32,15 +32,23 @@
const $ = (qs) => document.querySelector(qs);
const $$ = (qs) => Array.from(document.querySelectorAll(qs));
// === DOM & VARS =======
const DOM = {};
const DOM = {
colorButtons: $$('button[data-color]'),
};
// === INIT =============
const init = () => {};
const init = () => {
DOM.colorButtons.forEach((button) => {
button.addEventListener('click', onClickColorButton);
});
};
// === EVENTHANDLER =====
const onClickColorButton = (e) => {
document.body.style.backgroundColor = e.currentTarget.dataset.color;
};
init();
// Übung 12: Farbe wechsle dich
// Platziere drei Buttons (button-Tag) auf einer Seite mit den Texten »Red«, »Green« und »Blue«. Bei Betätigung eines Buttons soll sich der Hintergrund der Seite entsprechend färben.
})();
@@ -71,13 +71,39 @@
const $ = (qs) => document.querySelector(qs);
const $$ = (qs) => Array.from(document.querySelectorAll(qs));
const DOM = {};
const DOM = {
red: $('#input-red'),
green: $('#input-green'),
blue: $('#input-blue'),
rangeInputs: $$('.form-range'),
currentHexColor: $('#current-hex-color'),
currentColor: $('#current-color'),
};
// === INIT =============
const init = () => {};
const init = () => {
//
DOM.rangeInputs.forEach((el) => {
el.addEventListener('input', onChangeColor);
});
};
// === EVENTHANDLER =====
const onChangeColor = (e) => {
const r = DOM.red.valueAsNumber;
const g = DOM.green.valueAsNumber;
const b = DOM.blue.valueAsNumber;
const hexRed = Number(r).toString(16).padStart(2, '0').toUpperCase();
const hexGreen = Number(g).toString(16).padStart(2, '0').toUpperCase();
const hexBlue = Number(b).toString(16).padStart(2, '0').toUpperCase();
//
document.body.style.backgroundColor = `rgb(${r} ,${g} ,${b})`;
DOM.currentColor.textContent = `rgb(${r} ,${g} ,${b})`;
DOM.currentHexColor.textContent = `#${hexRed}${hexGreen}${hexBlue}`;
};
// === XHR/FETCH ========
// === FUNCTIONS ========
@@ -15,3 +15,13 @@
init();
})();
// <section id="info">
// <h3>
// <img src="it.png" alt="Italian Flag" title="Italian Flag">
// Colosseum
// </h3>
// <p>
// The Colosseum or Coliseum, also known as the Flavian Amphitheatre or Colosseo, is an oval amphitheatre in...
// </p>
// </section>
@@ -85,6 +85,21 @@
});
// TODO: Die letzten 3 Buttons mit Aktion zuweisen.
DOM.buttonCheckOn.addEventListener('click', (e) => {
e.preventDefault();
DOM.cbAgb.checked = true;
DOM.btnSend.disabled = false;
});
DOM.buttonCheckOff.addEventListener('click', (e) => {
e.preventDefault();
DOM.cbAgb.checked = false;
DOM.btnSend.disabled = true;
});
DOM.buttonCheckOnOff.addEventListener('click', (e) => {
e.preventDefault();
DOM.cbAgb.checked = !DOM.cbAgb.checked;
DOM.btnSend.disabled = !DOM.btnSend.disabled;
});
</script>
</body>
</html>
@@ -47,8 +47,9 @@
// === EVENTHANDLER =====
const onClickFontSize = (e) => {
const btnEl = e.currentTarget;
const label = btnEl.getAttribute('data-label');
const size = btnEl.getAttribute('data-size');
// const { label,size} = btnEl.dataset;
const label = btnEl.getAttribute('data-label'); // btnEl.dataset.label;
const size = btnEl.getAttribute('data-size'); // btnEl.dataset.size;
switch (label) {
case 'INCREASE':
setFontSize(currentFontSize() + 5);
@@ -57,7 +58,13 @@
setFontSize(currentFontSize() - 5);
break;
default:
setFontSize(size);
// setFontSize(eval(label));
// => eval('BIG') -> BIG // VORSICHT: eval ist evil
if (!isNaN(size)) {
setFontSize(size);
} else {
console.warn('not a valid size');
}
}
};