Hallo Auge
Ich nehm' mal ein Beispiel von mir. Das mag nicht unbedingt elegant sein, aber es funktioniert. Zum herumspielen sollte das Skript jedenfalls reichen.
Ich hoffe du nimmst es mir nicht übel, wenn ich dennoch etwas dazu schreibe. ;-)
/** * warte, bis das DOM geladen ist */ window.addEventListener("DOMContentLoaded", start, false);
Der dritte Parameter der Methode addEventListener
, über den bestimmt werden kann, für welche Ereignisphase der Eventhandler registriert werden soll, ist optional, und der Standardwert für diesen Parameter ist false
. Das heißt, wenn kein drittes Argument übergeben wird, dann wird der Eventhandler nicht für die Capturing-Phase registriert.
window.addEventListener('DOMContentLoaded', start);
Die Browser, bei denen eine explizite Angabe für diesen Parameter notwendig gewesen wäre, dürften mittlerweile wohl schon lange ausgestorben sein. Es ist aber natürlich kein Fehler false
anzugeben. Ich wollte nur mal erwähnt haben, dass das eigentlich nicht notwendig ist.
/** * registriere den Event-Listener für das aside #function_bar, * das ein Formular enthält, welches wiederum Buttons enthält */ function start() { var listen2Click = document.getElementById("function_bar"); listen2Click.addEventListener("click", switchClass, false); listen2Click.setAttribute("class", "js"); }
Gibt es auch ein aside function_foo
? – scnr ;-) Naja, wie auch immer, jedenfalls ist die Verwendung von setAttribute
hier nicht wirklich vorbildhaft. Ich hätte das wohl eher so geschrieben:
function start ( ) {
const aside = document.getElementById('function_bar');
aside.addEventListener('click', switchClass);
aside.classList.add('js');
}
Es ist meistens die beste Wahl mit classList
zu arbeiten, da hierbei nicht das Risiko besteht, dass ein Wert unbeabsichtigt überschrieben wird. Ansonsten wäre hier aside.className='js'
ebenfalls eine Alternative.
/** * Nachimplementation der PHP-Funktion in_array() (Helferfunktion) */ function inArray(item, array) { var arrayLen = array.length; for (p = 0; p < arrayLen; p++) { if (array[p] == item) return true; } return false; }
Wenn es darum geht herauszufinden, ob ein bestimmter Wert in einem Array enthalten ist, dann gäbe es zu diesem Zweck auch in JavaScript eine eingebaute Methode, nämlich Array.prototype.includes
.
console.info( [1, 2, 3].includes(2) ); // true
Je nach dem ob der als Argument übergebene Wert in dem Array ist, wird entweder true
oder false
zurückgegeben. Dabei wird im Übrigen der Vergleichsalgorithmus SameValueZero verwendet und nicht einfach auf strict equality geprüft. Allerdings, auch wenn includes
hier von der Semantik her das Mittel der Wahl sein sollte, muss dennoch erwähnt werden, dass diese Methode noch nicht überall implementiert ist, man also gegebenenfalls ein Polyfill bereitstellen müsste.
/** * Werte den erfolgten Klick aus, vergleiche den Wert des * geklickten Buttons mit den erlaubten Werten (Variable `possTargets`) * und weise den Wert des Buttons, wenn er nach der Prüfung mit in_array() * als erlaubt gilt, als Klassenname dem HTML-Element „body“ zu. */ function switchClass(e) { if (!e) e = window.event;
In einem Browser der mit dem Ereignismodell des DOM nichts anfangen kann, würde diese Funktion niemals aufgerufen werden. Die Prüfung ob ein Event-Objekt übergeben wurde kann man sich also sparen.
var klickTarget = e.target;
Zumal du dann hier konsequenterweise als Alternative noch e.srcElement
hättest anbieten müssen. ;-)
var targetName = ""; var possTargets = ["without_rework", "with_rework", "deletions"]; if (inArray(klickTarget.value, possTargets)) { targetName = klickTarget.value; } else { targetName = ""; }
Ich denke, das geht alles auch ein wenig eleganter, wie du ja selbst schon vermutet hast. Wobei ich bei meiner alternativen Version mal davon ausgehe, dass Array.prototype.includes
unterstützt wird, beziehungsweise dass ein Polyfill dafür bereitsteht.
function switchClass (event) {
const value = event.target.value,
name = [
"without_rework",
"with_rework",
"deletions"
].includes(value) && value;
// ...
}
Natürlich könnte man der Übersicht zuliebe hier für das Array auch eine Variable anlegen, also das muss nicht zwingend der Weisheit letzter Schluss sein. ;-)
var htmlBody = document.getElementsByTagName("body");
Die Methode getElementsByTagName
muss hier nicht wirklich bemüht werden, da das Body-Element, beziehungsweise seine DOM-Repräsentation über document.body
referenziert werden kann.
//var classValue = htmlBody[0].getAttribute("class"); if (targetName.length > 0) { htmlBody[0].setAttribute("class", targetName); } else { htmlBody[0].removeAttribute("class"); } }
Auch das schaut mir ein wenig sehr umständlich aus. Aber wie auch immer, im Folgenden nochmal alles kompakt zusammengefasst.
window.addEventListener('DOMContentLoaded', function ( ) {
const aside = document.getElementById('function_bar');
aside.addEventListener('click', function (event) {
const value = event.target.value,
list = ['without_rework', 'with_rework', 'deletions'];
document.body.className = list.includes(value) ? value : '';
});
});
Viele Grüße,
Orlok