Trennung von CSS und JavaScript
Es kann sein, dass Dir aufgefallen ist dass wir in allen vorhergehenden Beispielen zwar Wasser gepredigt, doch Wein getrunken haben.
Unser Fehler
Wir haben zwar die Struktur von dem Verhalten der Seite getrennt, andererseits aber Seitenstil per JavaScript definiert, was genauso schlecht ist.
Wir definierten den Seitenstil indem wir das style Attribut und
dessen Unterattribute veränderten:
if(!document.getElementById('errormsg')){
var em=document.createElement('p');
em.id='errormsg';
em.style.border='2px solid #c00';
em.style.padding='5px';
em.style.width='20em';
em.appendChild(document.createTextNode('Please enter
or change the fields marked with a '))
i=document.createElement('img');
i.src='img/alert.gif';
i.alt='Error';
i.title='This field has an error!';
em.appendChild(i);
}
Das bedeutet, dass wann immer wir das Aussehen unserer Erweiterungen ändern wollen, wir das im JavaScript vornehmen müssen, was weder praktikabel, noch besonders schlau ist.
Es gibt mehrere Möglichkeiten CSS-
Definitionen einem Element dynamisch hinzuzufügen. Eine Möglichkeit ist
es die ID zu ändern, indem wir das ID Attribut
neu belegen. Eine flexibelere Lösung ist Klassen hinzuzufügen, vor
allem weil ein Element mehrere Klassen haben kann.
Die Struktur mehrerer Klassen
Um in einem Element mehr als eine Klasse zu verwenden, müssen die Klassen
durch ein Leerzeichen getrennt hinzugefügt werden: <div class="special highlight kids">
Die meisten modernen Webbrowser unterstützen dies, ein paar haben jedoch
Fehler in der Implementierung. MSIE auf Macintosh mag beispielsweise keine Klassen, die
den Namen einer anderen beinhalten oder wenn vor der ersten oder nach der letzten
Klasse ein Leerzeichen steht.
Klassen per JavaScript hinzufügen
Um eine Klasse einem bestimmten Element hinzuzufügen, ändern wir dessen
className Attribut. Wenn wir beispielsweise das Aussehen eines
Menus ändern wollen, wenn der Browser DOM unterstützt,
geht das folgendermaßen:
HTML:
<ul id="nav">
[...]
</ul>
Javascript:
if(document.getElementById && document.createTextNode)
{
if(document.getElementById('nav'))
{
document.getElementById('nav').className='isDOM';
}
}
Das erlaubt uns in unserem CSS zwei verschiedene Aussehen zu definieren:
ul#nav{
[...]
}
ul#nav.isDOM{
[...]
}
Allerdings wird in dem vorherigen Beispiel jede Klasse, die dem Element bereits hinzugefügt wurde, überschrieben. Wir müssen also prüfen, ob das Element bereits eine Klasse hat, und wenn dem so ist, ein Leerzeichen gefolgt von der neuen Klasse anfügen.
if(document.getElementById && document.createTextNode)
{
var n=document.getElementById('nav');
if(n)
{
n.className+=n.className?' isDOM':'isDOM';
}
}
Das gleiche Problem tritt auf wenn wir Klassen entfernen, da manche Webbrowser
class="foo bar " nicht unterstützen. Auf die Dauer kann
das ziemlich nervig werden, daher ist es besser eine wiederverwendbare Funktion zu
schreiben, um diese Aufgabe zu erledigen.
function jscss(a,o,c1,c2)
{
switch (a){
case 'swap':
o.className=!jscss('check',o,c1)?o.className.replace(c2,c1): <-
o.className.replace(c1,c2);
break;
case 'add':
if(!jscss('check',o,c1)){o.className+=o.className?' '+c1:c1;}
break;
case 'remove':
var rep=o.className.match(' '+c1)?' '+c1:c1;
o.className=o.className.replace(rep,'');
break;
case 'check':
return new RegExp('\\b'+c1+'\\b').test(o.className)
break;
}
}
Diese Beispielfunktion erwartet vier Parameter
a- gibt an, welche Aktion die Funktion ausführen soll.
o- das Objekt, auf das die Aktion angewandt wird.
c1- der Name der ersten Klasse
c2- der Name der zweiten Klasse
Mögliche Aktionen sind:
swap- tauscht Klasse
c1gegen Klassec2aus. add- fügt Klasse
c1dem Objektohinzu. remove- löscht Klasse
c1. check- prüft, ob Klasse
c1schon dem Objektohinzugefügt wurde und gibttrueoderfalsezurück.
Als Beispiel wollen wir erreichen, dass der Besucher die Überschriften der zweiten Ebene aktivieren kann, um das darauf folgende Element zu verstecken und anzuzeigen. Weiterhin soll die Überschrift eine andere Klasse erhalten, wenn sie "aktiv" ist, oder wenn sich der Mauszeiger über ihr befindet.
CSS:
.hidden{
display:none;
}
.shown{
display:block;
}
.trigger{
background:#ccf;
}
.open{
background:#66f;
}
.hover{
background:#99c;
}
JS:
function collapse()
{
// überprüfe ob DOM vorhanden, ansonsten breche ab
if(!document.createTextNode){return;}
// Erstelle einen neuen Absatz, der erklärt, das die
// Überschriften aktivierbar sind
var p=document.createElement('p');
p.appendChild(document.createTextNode('Click on the headlines to
collapse and expand the section'));
// gehe durch alle Überschrifen der zweiten Ebene
var heads=document.getElementsByTagName('h2');
for(var i=0;i<heads.length;i++)
{
// nehme das nächste Element (die Schleife ist nötig,
// um Leerzeilenprobleme zu vermeiden
var tohide=heads[i].nextSibling;
while(tohide.nodeType!=1)
{
tohide=tohide.nextSibling;
}
// verstecke das Element, indem die Klasse hidden
// angefügt wird, und füge die Klasse
// 'trigger' an der Überschrift an
cssjs('add',tohide,'hidden')
cssjs('add',heads[i],'trigger')
// speichere das Element in einem Attriut
heads[i].tohide=tohide;
// füge der Überschrift bei Mausberührung
// die Klasse hover hinzu
heads[i].onmouseover=function()
{
cssjs('add',this,'hover');
}
// lösche die Klasse, wenn die Maus wegbewegt wird
heads[i].onmouseout=function()
{
cssjs('remove',this,'hover');
}
// wenn der Besucher die Überschrift aktiviert
heads[i].onclick=function()
{
// prüe, ob das folgende Element bereits
// die Klasse hidden hat
if(cssjs('check',this.tohide,'hidden'))
{
// ersetze hidden durch shown und trigger durch
// open
cssjs('swap',this,'trigger','open');
cssjs('swap',this.tohide,'hidden','shown');
} else {
// und umgekehrt
cssjs('swap',this,'open','trigger');
cssjs('swap',this.tohide,'shown','hidden');
}
}
// füge den neuen Absatz vor der ersten Überschrift ein
document.body.insertBefore(p,document.getElementsByTagName('h2')[0]);
}
function cssjs(a,o,c1,c2)
{
[...]
}
}
window.onload=collapse;
Probiere dieses Beispiel aus.
Auf diese Art und Weise haben wir Struktur, Darstellung und Verhalten der Webseite vollkommen getrennt und einen ziemlich komplexen Effekt erstellt. Die Abänderung dieses Effekts ist einfach und erfordert kein JavaScript-Wissen.
Sichere css.js für deine eigenen Versuche, indem du das
Ziel des Verweises auf deine Festplatte speicherst.
