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
c1
gegen Klassec2
aus. add
- fügt Klasse
c1
dem Objekto
hinzu. remove
- löscht Klasse
c1
. check
- prüft, ob Klasse
c1
schon dem Objekto
hinzugefügt wurde und gibttrue
oderfalse
zurü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.