Style, Attributs & ClassList

Dieses Kapitel ist ergänzend zur Seite Document Object Model (DOM). Hier sind noch Ergänzungen zu folgenden Objekten:

Wenn sie die JavaScript-Anweisunden dieser Seite testen möchten, kopieren sie den Inhalt in eine HTML-Datei innerhalb des body-Elements.

Das CSSStyleDeclaration-Object

Das CSSStyleDeclaration-Object beschreibt den Umgang mit Stylesheets und Style-Anweisungen. Ein elementares Werkzeug von JavaScript DOM ist das dynamische erzeugen oder ändern von Style-Angaben. Das CSSStyleDeclaration-Object wird mit der style-Eigenschaft an einem Element generiert.

var x = document.getElementById("myID").style;

Natürlich hat das CSSStyleDeclaration-Object eine length-Eigenschaft, einen Index dagegen nicht.

Das CSSStyleDeclaration-Object behandelt nur style-Anweisungen des style-Attributes im Element. Der Zugriff auf ein style-Element im head-Tag könnte so aussehen:

var x = document.getElementsByTagName("STYLE")[0];

Zugriff auf ein externes Stylesheet ist mit DOM nicht möglich!

Die Syntax

Die Schreibweise ist etwas abweichend von style-Angaben im HTML. Eine Angabe wie die folgende ist falsch:

var x = document.getElementById("myID").style.background-color: red;

In diesem Code sind gleich mehrere Fehler die in JavaScript nicht vorkommen dürfen:

  • background-color ist falsch, richtig ist backgroundColor (Camel Case)
  • Die Wertzuweisung ist das Istgleich (=) nicht der Doppelpunkt
  • Die Wertzuweisung muss in Anführungszeichen
var x = document.getElementById("myID").style.backgroundColor = "red";

Ein Vorteil des CSSStyleDeclaration-Object ist, dass bestehende style-Angaben nicht überschrieben werden. Wenn sie stattdessen die Methode element.setAttribute("style", "xx") verwenden werden alle bestehenden style-Angaben überschrieben. Eine Liste der möglichen Styles finden sie hier:

w3schools.com

Mehrere style-Eigenschaften zuweisen

Jede style-Anweisung ist eine Eigenschaft des CSSStyleDeclaration-Objects. Das Objekt kann viele Eigenschaften aufnehmen wie das folgende Beispiel zeigt:

<h1 id="myID">Headline</h1>
<button onclick="myFunction()">Klick mich!</button>

<script>
function myFunction() {
var x = document.getElementById("myID").style;
x.backgroundColor = "yellow";
x.color = "red";
x.border = "thick solid blue";
}
</script>     

Ein etwas komplexeres Beispiel

Dieses Beispiel stammt von wiki.selfhtml.org und zeigt Möglichkeiten vom Umgang mit JavaScript auf.

<p>Erster Absatz</p>
<p>Zweiter Absatz</p>
<p>Dritter Absatz</p>
<button onclick="myFunction()">Klick mich!</button>

<script>
function myFunction() {
for (var i = 0, p = document.getElementsByTagName("p"); i < p.length; i++) {
p[i].style.border = "5px solid #c32e04";
p[i].style.borderRadius = "10px";
p[i].style.backgroundColor = "#dfac20";
p[i].style.color = "#3983ab";
p[i].style.fontSize = "200%";
}
}
</script>     

Das NamedNodeMap-Object

Die attributes-Eigenschaft gibt eine unsortierte Sammlung (Collection) aller Attribute des angegebenen Elements, als NamedNodeMap-Object zurück. Auf Knoten in einem NamedNodeMap-Object kann mit dem Namen oder den Index zugegriffen werden. Die Reihenfolge, in der die Attribute gespeichert sind, ist nicht definiert. Sie können sich nicht darauf verlassen, dass attributes[0] tatsächlich das erste, im HTML-Code notierte, Attribut ist. Diese Notation ist nur dazu gedacht, einfache Zählschleifen zu erlauben.

var x = document.getElementById("myID").attributes[0]; // attributes Index

Methoden und Eigenschaften des NamedNodeMap-Object

  • nodemap.getNamedItem() / liefert einen Attribut-Knoten einer NamedNodeMap bzw. ein Attr-Objekt
  • nodemap.item() / liefert den Attribut-Knoten eines Index, einer NamedNodeMap bzw. ein Attr-Objekt
  • nodemap.length / liefert Anzahl der Attribut-Knoten
  • nodemap.removeNamedItem() / löscht einen Attribut-Knoten
  • nodemap.setNamedItem() / erzeugt einen Attribut-Knoten mit dem Namen

Im folgenden Beispiel werden (fast) alle Methoden und Eigenschaften des NamedNodeMap-Object aufgerufen und zurückgegeben.

<div id="myID" class="myClass" style="color: blue">
Hallo Welt!</div>
<button onclick="myFunction()">Klick mich!</button>

<script>
function myFunction() {
var myDiv = document.getElementById("myID").attributes;
var x = myDiv.getNamedItem("id").value;  // liefert myID
var y = myDiv.item(1).name;  // liefert id ????
myDiv.removeNamedItem("style"); // löscht style
var z = myDiv.length; // liefert 2
var output = "<pre>getNamedItem: "+x+"\nitem: " + y+"\nlength: "+z+"\n</pre>";
document.getElementById("myID").innerHTML = output;
}
</script>

Die setNamedItem()-Methode

Die setNamedItem()-Methode fügt einen definierten Knoten (ein Attribut) in das NamedNodeMap-Object ein. Dazu sind allerdings einige Schritte notwendig:

  • Ein Elementobjekt für das neue Attribut
  • Die createAttribute()Methode für den Attributnamen
  • Die value-Eigenschaft für die Wertzuweisung
  • Die setNamedItem()-Methode zum hinzufügen

Im Beispiel wird dem div-Element das Attribut contenteditable zugewiesen und auf true gestellt. Nach dem Button-Klick soll das Element editierbar sein.

<div id="myID" class="myClass" style="color: blue">
Hallo Welt!</div>
<button onclick="myFunction()">Klick mich!</button>

<script>
function myFunction() {
var myDiv = document.getElementById("myID"); // Elementobjekt
var typ = document.createAttribute("contenteditable"); // erzeugt Attr-Object
typ.value = true; // Wertzuweisung
myDiv.attributes.setNamedItem(typ); // Attributknoten
}
</script>

Das ist sehr Aufwendig und empfiehlt sich dann, wenn ein Attribut und sein Wert für mehrere Elemente gebraucht wird. Ansonsten empfiehlt sich hier die setAttribute()-Methode.

<script>
function myFunction() {
var myDiv = document.getElementById("myID"); // Elementobjekt
myDiv.setAttribute("contenteditable", true);
}
</script>

Das Attr-Object

Während das NamedNodeMap-Object eine Collection der Attribute eines Elements beschreibt, behandelt das Attr-Object ein einzelnes Elementattribut. Damit ein Attribut ansprechbar ist, müssen wir es zuerst finden, z.B. mit:

Nachdem ein Attr-Object bekannt ist stehen folgende Eigenschaften zur Verfügung:

Ein Attr-Object erzeugen

Ein NamedNodeMap-Object stellt Index bzw die item-Methode zur Verfügung, allerdings ist die Liste unsortiert und damit nicht sicher, ob auch das richtige Attr-Object gefunden wird.
Im Beispiel soll das erste Attribut der Collection gefunden werden (id) und mit der value-Eigenschaft der Attributwert ausgelesen werden (myID)!

<div id="myID" class="myClass" style="color: blue">
Hallo Welt!</div>
<button onclick="myFunction()">Klick mich!</button>

<script>
function myFunction() {
var x = document.getElementById("myID").attributes[0].value;
// oder var x = document.getElementById("myID").attributes.item(0).value;
document.getElementById("myID").innerHTML = x;
}
</script>

Sicherer geht das mit der getNamedItem-Methode.

<div id="myID" class="myClass" style="color: blue">
Hallo Welt!</div>
<button onclick="myFunction()">Klick mich!</button>

<script>
function myFunction() {
var x = document.getElementById("myID").attributes.getNamedItem("id").value;
document.getElementById("myID").innerHTML = x;
}
</script>

Ein Attr-Object mit createAttribute()

Mit der createAttribute()-Methode des Document-Objects wird ein Attr-Object generiert und mit der value-Eigenschaft ein Wert zugewiesen. Das Attribut wird dann allen p-Elementen im Dokument zugewiesen.

<style>
.myClass {
color: blue;
border:#000 thin solid;
background-color:#0F0;
padding:20px;
font-size:1.5em;
}
</style>
<p>Erster Absatz</p>
<p>Zweiter Absatz</p>
<p>Dritter Absatz</p>
<button onclick="myFunction()">Klick mich!</button>

<script>
var x = document.getElementsByTagName("P");

function myFunction() {
for (var i = 0; i < x.length; i++) {
var typ = document.createAttribute("class");
typ.value = "myClass";
x[i].attributes.setNamedItem(typ);
}}
</script>

Eigenschaften des Attr-Objects

Es stehen drei Eigenschaften zur Verfügung wobei die name. Eigenbschaft nur Lesezugriff hat.

<style>
.firstClass {
color: white;
border:#000 thin solid;
background-color: black;
padding:20px;
font-size:1.5em;
}
.secondClass {
color: blue;
border:#000 thin solid;
background-color:#0F0;
padding:20px;
font-size:1.5em;
}
</style>

<div id="myID" style="color: blue" class="myClass">
Hallo Welt!</div>
<button onclick="myFunction()">Klick mich!</button>

<script>
function myFunction() {
var x = document.getElementById("myID").attributes;
var y = x.getNamedItem("class");
var z = y.specified;
alert("Attribut existiert?: " + y.specified + "\nAttributname: " + y.name);
y.value = "secondClass";
}
</script>

Der Weg zu einem Attr-Object

Irgendwo steht geschrieben: "In JavaScript ist alles ein Objekt!" Ausserdem gibt es irgendwo die Aussage: "Wer JavaScript-Objekte verstanden hat, hat das Programm verstanden!"
Objekte haben Eigenschaften, diese können wiederum zu Objekten führen, das ist schon ein bisschen verwirrend, darum habe ich hier ein kleines Beispiel über Objekthierarchien in JavaScript geschrieben:

<div id="myID" style="color: blue" class="myClass">
Hallo Welt!</div>
<button onclick="myFunction()">Klick mich!</button>

<script>
var a = document.getElementsByTagName("DIV"); // das ist ein NodeList-Object
var b = a[0]; // das ist ein element-Object
var c = b.attributes; // das ist ein NamedNodeMap-Object
var d = c.getNamedItem("class"); // das ist ein Attr-Object
var e = d.value; // value ist eine Egenschaft des Attr-Objects
window.alert(e); // alert ist eine Methode des window-Objects
</script>

Verstanden????????????

Das DOMTokenList-Object

Der Name eines class-Attributs kann mit der Eigenschaft className ausgelesen oder geändert werden, auch wenn mehr als eine Klasse notiert ist. Es werden dann alle Klassen als String zurückgegeben.

<p id="myID" class="firstClass secondClass thirdClass">Adi <em>Prinz</em></p>
<button onclick="myFunction()">Klick mich!</button>

<script>
function myFunction() {
var x = document.getElementById("myID");
var y = x.className;
x.innerHTML = "Klassenname in diesem Element: " + y;
}
</script>     

Der Zugriff auf die einzelnen Klassen eines Elements kann mit der classList-Eigenschaft erreicht werden. Mit der classList-Eigenschaft erzeugen sie ein neues Objekt, das DOMTokenList-Object, welches eine Liste aller Klassen des Elements repräsentiert.

<p id="myID" class="firstClass secondClass thirdClass">Adi <em>Prinz</em></p>
<button onclick="myFunction()">Klick mich!</button>

<script>
function myFunction() {
var x = document.getElementById("myID").classList.length; //liefert 3
alert(x);
}
</script>

Das DOMTokenList-Object hat auch eine length-Eigenschaft und noch weitere Eigenschaften und Methoden. Index steht nicht zur Verfügung, dafür gibt es die item- Methode.

Eigenschaften und Methoden des DOMTokenList-Objects

  • tokenlist.add(class1, class2, ...) / Klassennamen anfügen
  • tokenlist.contains(class) / prüfen ob Klassenname existiert (true(false)
  • tokenlist.item(index) / Index
  • tokenlist.remove(class1, class2, ...) / löscht Klassennamen
  • tokenlist.toggle(class, true|false) / Toggle zwischen Klassennamen
  • length / Anzahl

Klassnnamen hinzufügen oder löschen

Klassennamen können hinzugefügt (add) oder auch gelöscht werden (remove). contains prüft, ob eine Klasse existiert.

<style>
.firstClass {
color: blue;
border:#000 thin solid;
background-color:#0F0;
padding:20px;
font-size:1.5em;
}
</style>

<p id="myID" class="firstClass secondClass thirdClass">Adi <em>Prinz</em></p>
<button onclick="myFunction1()">Klick mich zum Prüfen!</button><br>
<button onclick="myFunction2()">Alle Klassen löschen!</button>

<script>
function myFunction1() {
var x = document.getElementById("myID");
var y = x.classList.contains("firstClass");
if (y == true) {
alert("Die Klasse existiert bereits!");
} else {
x.classList.add("firstClass");
alert("Die Klasse wurde angefügt!");
}}

function myFunction2() {
var x = document.getElementById("myID");
var y = x.classList.remove("firstClass", "secondClass", "thirdClass");
}
</script>     

Toggle

Toggle oder Hin- un Her-Schalten ermöglicht einen switch zwischen zwei Klassennamen. Die toggle-Methode toggelt eine Klasse in die classList hinein bzw. hinaus. Beim ersten Aufruf wird die Klasse eingeschaltet, beim zweiten Aufruf wird die Klasse entfernt.

<style>
.firstClass {
color: blue;
border:#000 thin solid;
background-color:#0F0;
padding:20px;
font-size:1.5em;
}
.secondClass {
color: white;
border:#000 thin solid;
background-color:black;
padding:20px;
font-size:1.5em;
}
</style>
<p id="myID" class="secondClass">Adi <em>Prinz</em></p>
<button onclick="myFunction()">Klick mich!</button>

<script>
function myFunction() {
document.getElementById("myID").classList.toggle("firstClass");
}
</script>     

Die toggle-Methoden kennt noch einen zweiten, optionalen Parameter true oder false. Mit true wird der Klassenname angefügt, mit false wird der Klassenname entfernt.

element.classList.toggle("firstClass", false); 
element.classList.toggle("firstClass", true);