Damit HTML-Elemente unterschiedlich aussehen können, dienen Cascading
Style Sheets, kurz: CSS. In einem Stylesheet werden die Regeln definiert, wie
das HTML-Markup darzustellen ist. Jede Regel besteht aus mindestens einem
Selektor (z.B. #box für das Element mit der ID "box") und einer
beliebigen Zahl "Eigenschaft:Wert;"-Paaren (z.B. border:0;).
In DynamischemHTML, der Verbindung von HTML, JavaScript und CSS, ist es nun üblich,
den Eigenschaften der HTML-Elemente mittels JavaScripts style direkt
neue Werte zuzuweisen (z.B. document.getElementById("box").style.border="0";)
und dann mit style auch wieder auszulesen, oder aber das
HTML-Element mit className insgesamt einer neuen Klasse (für
die andere Stile gelten) zuzuordnen (z.B. document.getElementById("box").className="important";),
bzw. dann mit currentStyle auf dem Internet Explorer und getComputedStyle()
auf W3C-kompatiblen Browsern den gültigen Stil auszulesen (was auch über
die schon unterschiedliche Syntax der Browser hinaus nicht ganz unproblematisch
ist - aber das ist ein anderes Thema).
Weniger bekannt ist hingegen die Möglichkeit, nicht den HTML-Elementen
sondern den CSS-Regeln neue Eigenschaften und Werte zuzuweisen, denn
JS hat auch Zugriff auf das DOM CSS
und kann!
Eigentlich verblüffend, denn schließlich ist dies so, als wenn CSS nur
ID-Selektoren kennen würde (z.B. #box für <div id="box">),
nicht jedoch die so mächtigen Klassen- oder Tag-Selektoren (z.B.
.box für <div class="box"> oder p für <p>),
die gleich für eine Vielzahl von HTML-Elementen stilgebend sind.
Die hier vorgestellte Funktion erlaubt es, bestehende CSS-Regeln & -Stile
abzufragen bzw. zu ändern (eine Funktion, um einfach mit JavaScript komplett
neue Stylesheets und CSS-Regeln zu erzeugen, habe ich als addStyle()
veröffentlicht).
Selbst bei Änderung an vielen Elementen ist es üblich, diese mittels JavaScript
einzeln durchzugehen, und jeweils die gewünschte Eigenschaft oder zumindest den
Klassennamen zu verändern. Wenn man hingegen einfach die CSS-Regel selbst
ändert, ergeben sich folgende Vorteile:
Mit nur einer Anweisung können alle HTML-Elemente abgehandelt werden,
für die der Selektor dieser Regel zutrifft (1 Änderung / x-fache
Wirkung - egal ob 10 oder 10000 Elemente davon betroffen sind).
Es lassen sich auch viele Stile auf einen Schlag ändern, indem man eine
komplette Regel mit mehreren Stilen ändert, anstatt jeden zu ändernden
Stil einzeln.
Der Stil der HTML-Elemente kann geändert werden, bevor diese
HTML-Elemente überhaupt existieren, also noch vor dem Beginn des
BODY-Tags (herkömmlich kann dies nur nachträglich geschehen,
z.B. im onLoad-Event, nachdem die HTML-Elemente bereits existent oder
gar sichtbar waren).
Anmerkung: Dies
gilt leider nicht für die allerersten Safari-Browser. Sie können
erst nach dem Laden des Dokuments auf die Stylesheets zugreifen. Die aktuellen
Safari-Browser sind hingegen standardkonform und schaffen das problemlos.
Anders als bei der direkten Stiländerung (die für alle Ausgabemedien
gültig ist), lassen sich hier gezielt für einzelne Geräte Stile
auslesen & ändern. D.h., für die Druckausgabe andere Stile, als
für die Bildschirmausgabe, oder Handhelds, oder ...
Falls man also z.B. das Layout dynamisch auf die Browsergröße
anpassen möchte, ist es also über diesen Weg möglich (und auch
sehr sinnvoll), wirklich nur das Bildschirmlayout zu ändern, während
z.B. das Drucklayout unverändert bleibt.
Ebenfalls lassen sich Pseudoformate (z.B. die Pseudoklasse :hover
oder das Pseudoelement :first-letter) nur auf diesem
Weg auszulesen & ändern.
Außerdem: Sämtliche Stile die innerhalb von JavaScript mit style
verwendet werden, werden üblicherweise auch innerhalb von JavaScript
definiert. Übersichtlicher ist es jedoch, alle Stile in einem
Stylesheet zu deklarieren. Dort werden sie zwar ggf. gar nicht gebraucht,
sie können dort jedoch einfach ausgelesen und dann innerhalb des Scripts
verwendet werden. Eine perfekte Trennung zw. (semantischem) HTML, Scripting
und den Layoutanweisungen ist somit leicht möglich.
Einige dieser Möglichkeiten können auch beim mehr und mehr in Mode kommenden
"unobtrusive JavaScript" (USJ) von Bedeutung sein, das aus einer möglichst
strikten Trennung von Script und HTML besteht. Soll eine Webseite beispielsweise mit
JavaScript stilistisch verändert werden, z.B. indem man Daten versteckt, um sie
erst auf Userwunsch hin wieder sichtbar zu machen, so kann das nur über statisches
CSS oder dynamisches JavaScript erfolgen (die Daten selbst sollen ja - abwärtskompatibel
für alle Browser wie auch für Suchmaschinen - bereits in der Webseite enthalten
sein). Die CSS-Variante ist unpraktikabel, da User ohne Scripting von den versteckten
Daten dann ausgeschloßen würden. Die übliche JavaScript-Variante durch Ändern
der Eigenschaft oder des Klassennamens hat hingegen den Nachteil, daß dies erst
dann geschehen kann, wenn das Element bereits existiert. Das bedeutet: Entweder
steht der notwendige Scriptcode direkt in der Webseite (möglichst sogar direkt
hinter dem jeweiligen Element - was dem Grundgedanken des UJS natürlich zuwider
läuft), oder er wird, so ist es üblich, erst dann aufgerufen, wenn die Seite
fertig geladen ist (gestartet durch das Onload-Event). Das bedeutet aber,
daß der Besucher sehen kann, wie sich die fertig geladene Webseite vor seinen
Augen gravierend ändert - ggf. obwohl er bereits mit dem Studium des Inhalts
begonnen hat. Ein hoher Nutzen also für den Webautor, durch die problemlose
Scriptanwendung dank UJS - eine unschöne wie irritierende "Zappelei" für den
Besucher ...
Leider haben die Browser zum einen jedoch eine unterschiedliche Syntax, um auf
CSS-Regeln zuzugreifen, zum anderen interpretieren sie den CSS-Code
selbst ebenfalls noch unterschiedlich, so daß der intern dann tatsächlich
benutzte CSS-Code sich ebenfalls noch von Browser zu Browser unterscheiden
kann - sowohl was den realen Inhalt bzw. die Form einer Regel angeht, als auch
ihre Position innerhalb des internen CSS-Codes (Beispiele für diese
eigenwillige Interpretationen listet die Seite Change style sheet
auf) - deswegen ist diese Vorgehensweise wohl auch nicht so sehr verbreitet.
Mit der hier vorgestellten Funktion cssRule() kann
nun sowohl eine komplette CSS-Regel als auch eine einzelne Eigenschaft
einer CSS-Regel browserübergreifend ausgelesen oder geändert
werden - mit Ausnahme von Apples Browser Safari auch bevor die betreffenden
HTML-Elemente existieren (und damit für den Surfer unsichtbar): direkt
zwischen den Stildefinitionen im HEAD-Bereich und dem HTML-Body.
Generell können (momentan) allerdings keine importierten Regeln (@import)
angesprochen werden! Es sind nur Stylesheets verarbeitbar, die intern mit dem
STYLE-Tag (<style type="text/css">)
oder als externe Datei mit dem LINK-Tag (z.B.
<link rel="stylesheet" type="text/css" href="sheet.css">)
eingebunden wurden - natürlich nur, sofern das Stylesheet vom der gleichen
Domain eingebunden wurde (JavaScripts "Same Origin Policy" verbietet ja aus
Sicherheitsgründen den Zugriff auf Daten einer fremden Domain).
Der Funktionsaufruf:
cssRule([target[,attribute[,value]]])
Der 1. Parameter target bestimmt die zu bearbeitende CSS-Regel.
Mögliche Werte für target sind:
Ein String, der den gewünschten Selektor enthält (nicht case-sensitive,
also unabhängig von Groß/Kleinschreibung). Beispiele: p für
Paragraphen-Elemente (<p>), #myId für
das Element mit der ID myId (<p id="myId">),
.myClass für Elemente der Klasse myClass
(<p class="myClass">) etc. (auch komplexere Selektoren sind
möglich).
Außerdem kann dem Selektor ein Begrenzer angehängt werden, um die Suche auf
bestimmte Stylesheets zu beschränken: selector@clipper.
Ist der Begrenzer eine Zahl, so wird er als Nummer des gewünschten
Stylesheets interpretiert (.myClass@0 sucht den Klassen-Selektor
myClass nur im 1. Stylesheet). Andernfalls wird der Begrenzer als
Medientyp interpretiert, wie er im media-Attribut des Style-Tags
Verwendung findet (also z.B. .myClass@print, um die Regel des
Klassen-Selektors myClass anzusprechen, welches sich aber
in einem Drucker-Stylesheet befinden muß:
<style type="text/css" media="print">).
Wird kein Begrenzer oder ein * als Medientyp übergeben (z.B.
.myClass oder .myClass@*), so werden alle
Stylesheets durchsucht (also z.B. <style type="text/css" media="print">,
<style type="text/css" media="screen"> &
<style type="text/css">). Hängt man einen
"leeren" Medientyp an (z.B. .myClass@), so werden nur
allgemeine, unspezifizierte Stylesheets durchsucht (<style type="text/css">).
Es werden dann alle Regeln der gewünschten Stylesheets durchsucht,
beginnend bei der letzten Regel (wenn mehrere Regeln mit gleichem
Selektor existieren, überschreibt die spätere Regeln die frühere).
Stimmt der Selektor einer Regel mit dem gesuchten Selektor überein,
so wird die Suche beendet.
Achtung: Gruppierte Selektoren,
z.B. in p, div, pre { }, werden von den Browsern unterschiedlich verwaltet!
Während z.B. Mozilla ab Version 1.75 hier (korrekterweise) auch nur eine
Regel mit genau diesem Selektor hat (und eine Änderung dieser Regel sich auch
auf alle drei Elemente gleichzeitig auswirkt), verwalten andere Browser (auch
ältere Mozillas) intern drei gleichlautende, aber voneinander getrennte,
Regeln mit dem jeweiligen Einzel-Selektor (hier also als würde man schreiben
p { }, div { } & pre { })! Die Gruppierung
existiert intern nicht - und kann somit auch nicht gefunden werden. Um diesem
Unterschied entgegenzuwirken, kann cssRule() auch im aktuellen
Mozilla (oder anderen standardkonformen Browsern) diese Regel unter jedem
einzelnen der Gruppen-Selektoren finden und ansprechen. Sonderfall Safari: Zmindes die ersten Safaris haten hier einen üblen
Fehler. Es wurde intern weder der korrekte Gruppen-Selektor, noch
alle Selektoren der Gruppe einzeln verwaltet! Stattdessen konnte man auf die Regel
nur mit dem 1. Selektor der Gruppe zugreifen - im Beispiel also p. Die
restlichen Selektoren div & pre waren ihnen unbekannt.
Ein String mit der "Adresse" (Pointer) der gewünschten Regel in der Form
"Nr. des Stylesheets/Nr. der Regel", jeweils beginnend bei 0.
Gültig sind also z.B. 0/0 (erstes Stylesheet/erste Regel),
1/4 (zweites Stylesheet/fünfte Regel) etc.
Achtung: Bei komplexeren Stylesheets und komplexeren Selektoren ist,
trotz gleichen CSS-Codes, die browserinterne Reihenfolge unter Umständen
von Browser zu Browser unterschiedlich! Wird z.B. @import
benutzt, so können bei dieser Adressierung nur Styles vor dem ersten
@import browserübergreifend identisch bearbeitet werden
(und selbst dann nicht immer). Diese Art der Adressierung empfiehlt sich
also nur dann, wenn man entweder "einfache" Stylesheets verwendet, oder
aber "weiß, was man tut". Man kann sich aber den auf dem aktuellen
System gültigen Pointer mittels Schlüsselwort rulepointer
als 2. Parameter (s.u.) auch von cssRule() selbst ermitteln lassen.
Ein Objekt, genauer: das Style-Objekt einer Regel, wie es diese Funktion
auch mit der Schlüsselanweisung styleobject ermitteln
kann. Wird eine Regel mehrfach angesprochen, so kann man sich auf
diese Art die "Neusuche" ersparen - selbst wenn das nur bei extrem vielen
& großen Stylesheets vielleicht von praktischer Relevanz sein könnte.
Wird kein Parameter übergeben, so wird nur getestet, ob der Browser
die benötigte Funktionalität für dynamische CSS-Regeln
überhaupt aufweist (der Browser Opera ist hier - mal wieder - bis zur
Version 9 exkl. das Sorgenkind der JavaScript-Entwicklergemeinde).
Die eigentliche Aktion wird durch die weiteren (optionalen) Parameter bestimmt:
Der 2. Parameter attribute ist ein String und kann folgende
Bedeutungen besitzen:
Enthält der 2. Parameter eine CSS-Eigenschaft, so wird nur der in der
Regel spezifizierte Wert dieser Eigenschaft verarbeitet. Dabei kann die
Eigenschaft sowohl in der CSS- (font-size) als auch
in der JavaScript-Syntax (fontSize) übergeben werden. Zu
bevorzugen ist allerdings die CSS-Syntax, da hier alle Browser eine
identische Syntax beherrschen, die JavaScript-Syntax allerdings von
Browser zu Browser unterschiedlich sein kann (CSS: float /
IEs JScript: styleFloat / Mozillas JavaScript bzw. ECMAScript:
cssFloat). cssRule() wandelt die CSS-Syntax
automatisch in die (intern benötigte) jeweils korrekte
JavaScript-Syntax um.
Der 2. Parameter kann auch ein Schlüsselwort enthalten, um eine spezifische
Aktion zu veranlassen. Folgende Schlüsselwörter werden z.Zt. unterstützt:
Bei fehlendem bzw. leerem 2. Parameter oder rule wird die komplette
zum übergebenen Selektor gehörende Regel verarbeitet.
Mit sheetobject wird das JavaScript-StyleSheet-Objekt
ermittelt, dem die Regel angehört. Dieses Objekt kann zur weiteren
Verarbeitung nützlich sein. Z.B. kann man so den URL auslesen, sofern
es sich um ein externes Stylesheet handelt (also bei Einbindung von
<link rel="stylesheet" type="text/css" media="print" href="printer.css">
und dort enthaltenem .myClass { color: red; } kann man mit
cssRule(".myClass@print","sheetobject").href den URL
des Stylesheets auslesen - beim Mozilla ist das der vollständige
URL, beim Internet Explorer der tatsächliche Inhalt des Attributs
href), jedenfalls sofern der Zugriff auf das Stylesheet erlaubt
ist. Weitere sinnvolle Eigenschaften sind hier u.a. title,
um auf den Titel des Stylesheets zugreifen zu können, oder
disabled, um festzustellen, ob das Stylesheet aktiviert
ist.
Achtung: Bei
"alternativen Stylesheets" bzw. der Eigenschaft disabled haben
ältere Versionen einiger Browser, mindestens Konqueror und Safari, einen
Bug, der eine Nutzung der "alternativen Stylesheets" unmöglich macht! Meines
Erachtens ist die Nutzung alternativer Stylesheets, jedenfalls so, wie es die
Browser bislang anbieten, ohnehin nur bedingt sinnvoll, da das vom Surfer
ausgewählte Stylesheet jeweils nur für das aktuelle Dokument gilt.
Als sinnvollere Lösung, bzw. auch als Workaround, bietet sich eher eine
eigene "Stylesheet-Verwaltung" an. Dabei kann dem Surfer eine Liste mit
unterschiedlichen Stylesheets angeboten werden. Der URL des gewählten
Sheets kann dann z.B. in einem Cookie gesichert werden, damit die Auswahl auf
der ganzen Website nutzbar ist. Der Autor muß dann nur auf jeder Seite
dem LINK-Element mittels der Eigenschaft href den ausgesuchten
URL zuweisen.
Bei sheetindex wird die Index-Nummer des gefundenen Stylesheets
als Integerzahl übergeben. Wurde kein passendes Stylesheet gefunden, so
wird NaN ("Not a Number") zurückgegeben anstelle des sonst
üblichen false.
Bei rulepointer wird ein Pointer auf die gefundene Regel
als String in der Form "Nr. des Stylesheets/Nr. der Regel" übergeben.
Dieser Pointer kann cssRule() auch im 1. Parameter target
als Zielreferenz übergeben werden. Der Pointer kann dabei, abhängig
vom Quellcode, von Browser zu Browser unterschiedlich sein. D.h., ein
auf einem Mozilla 1.8 ermittelter Pointer kann sich, bei identischem
Quellcode, von einem auf Mozilla 1.5 ermittelten Pointer bereits unterscheiden!
Konnte auf ein spezifiziertes Stylesheet nicht zugegriffen werden, weil
dieses von einer fremden Domain eingebunden wurde ("Same Origin Policy"),
so wird hier ein Leerstring zurückgegeben anstelle des sonst
üblichen false.
Mit rulecollection erhält man die JavaScript-Collection
der Regeln des gefundenen Stylesheets. Hiermit ist es z.B. möglich, direkt
und browserübergreifend auf die Regeln zuzugreifen. So kann man auch
mit der Eigenschaft length die Anzahl der Regeln im Stylesheet ermitteln
(alert(cssRule("0/0","rulecollection").length)).
ruleobject übergibt das JavaScript-Objekt der gefundenen
Regel. Hiermit ist es z.B. möglich, den Selektor-Text auszulesen,
den der Browser intern bei dieser Regel verwendet
(alert(cssRule("0/0","ruleobject").selectorText)).
Mit styleobject kann man das JavaScript-Style-Objekt
der CSS-Regel selbst ermitteln. Mit diesem Objekt läßt sich
dann in JavaScript weiterarbeiten. Es entspricht der Syntax
cssRule("0/0","ruleobject").style,
und kann cssRule() ebenfalls im 1. Parameter target als
Zielreferenz übergeben werden.
Mit ownerobject kommt man browserübergreifend an das HTML-Element
heran, mit dem die Styles eingebunden sind, um die entsprechenden Eigenschaft nutzen
zu können. Beispiele: cssRule("0/0","ownerobject").tagName
für den Namen des Style-Tags ("LINK" oder "STYLE") oder mit
cssRule("0/0","ownerobject").href
den URL eines externen Stylesheets, sofern vorhanden. Da hier direkt auf den
eigenen HTML-Code zugegriffen wird, funktioniert dies auch dann, falls das
Stylesheet als Datei eingebunden wurde, die auf einem fremden Server liegt.
Außerdem kann hiermit auch der URL geschrieben werden. Man kann
also das gefundene Stylesheet auch gegen ein anderes austauschen.
In die gleiche Kategorie gehört ownermarkup. Hier wird der
(vom Browser interpretierte!) HTML-Quellcode des Style-Tags
übergeben. Dies ist also entweder das STYLE-Element inkl. den Styles,
oder aber das LINK-Element - jeweils inkl. ihrer Attribute. D.h., ein
cssRule("0/0","ownermarkup") entspricht
einem cssRule("0/0","ownerobject").outerHTML
auf dem IE. Das Script bildet die Funktionalität von outerHTML
einfach nach, da es sich dabei um eine proprietäre Eigenschaft des
IEs handelt, die von vielen anderen Browsern überhaupt nicht oder
nicht identisch unterstützt wird.
Achtung: Die Angabe eines Schlüsselwortes kann nur dann erfolgen,
wenn als 1. Parameter ein Selektor-Text oder ein Pointer (s. rulepointer),
nicht jedoch, wenn das Style-Objekt einer Regel (s. styleobject)
übergeben wurde! Im letzteren Fall greift cssRule() direkt
auf dieses Objekt zu, ohne danach zu suchen bzw. das Stylesheet zu "kennen".
Wird ein 3. Parameter value übergeben, so wird die Regel bzw.
Eigenschaft mit dem hier übergebenen Wert geändert.
Folgende Werte werden von der Funktion zurückgegeben:
false wenn der Aufruf nicht erfolgreich war. Sei es, daß der
Browser zu alt ist, sei es, daß der gesuchte Selektor nicht gefunden wurde.
Achtung: Beim Firefox 3
ist nicht nur, wie üblich, der Zugriff auf von fremden Domains
eingebundene externe Stylesheets verboten ("Same Origin Policy"). Auch wenn
man die HTML-Seite, nebst CSS-Datei, von einem lokalen Laufwerk lädt,
wird der Zugriff (mit einem Chrome-Fehler) verweigert - zumindest
standardmäßig. Da cssRule() aber generell unerlaubte
Zugriffe abfängt, wird auch in diesem Fall nur ein false
als Funktionsergebnis zurückgegeben.
Achtung: Beim
Browser Konqueror wird ggf. nur ein false zurückgegeben,
falls attribute leer oder rule ist, da alte
Versionen einen Bug bei der zur Verarbeitung der kompletten Regel
notwendigen JavaScript-Eigenschaft cssText haben.
Ein JavaScript-Objekt wenn attribute ein
"Objekt-Schlüsselwort" enthält. Bei
sheetobject das StyleSheet-Objekt, dem die Regel angehört.
rulecollection die JavaScript-Objekt-Collection aller Regeln
des Stylesheets, dem die gefundene Regel angehört
ruleobject das Objekt der gefundenen Regel selbst
styleobject das Style-Objekt der Regel
ownerobject das Objekt des HTML-Elements des Stylesheets
Verschiedene Datentypen, wenn attribute ein anderes
Schlüsselwort enthält. Bei
sheetindex eine Integerzahl mit der Index-Nummer des gefundenen
Stylesheets, oder NaN, falls kein passendes Stylesheet gefunden wurde
rulepointer ein String in der Form "Nr. des Stylesheets/Nr. der
Regel" als Pointer auf die gefundene Regel, oder ein Leerstring, falls der Zugriff
auf das Stylesheet nicht erlaubt ist
ownermarkup der (interpretierte) HTML-Quellcode des Stil-Elements
Abhängig vom 3. Parameter:
Wenn kein value übergeben wurde:
Komplette Regel, wenn attribute leer oder rule ist
oder den Stil der Eigenschaft, die in attribute spezifiziert wurde.
Wenn value übergeben wurde (auch bei Leerstring): true, wenn die Regel oder Eigenschaft neu gesetzt werden konnte.
regel=cssRule(".aStil") um den Text der
letztenaller Regeln für die Klasse aStil auszulesen
- also: display: none;
regel=cssRule(".aStil@") um den Text der
(letzten) allgemeinen (also für alle Medien geltenden) Regel
für die Klasse aStil auszulesen - also:
font-size: 2em; font-weight: bold;
groesse=cssRule(".aStil@","font-size") um die in dieser
Regel definierte Fontgröße auszulesen - also: 2em
status=cssRule(".aStil@","","font-size:
3em; font-weight: normal";) um den Text diese Regel komplett
zu ändern. Wenn status den Wert true hat, dann
lautet die Regel nun .aStil { font-size: 3em;
font-weight: normal; }
Sollte status aber false sein, so gilt nach wie vor
die ursprüngliche Regel - der Browser ist zu alt (oder hat einen Bug).
status=cssRule(".aStil@","font-size","3em")
um die in dieser Regel definierte Fontgröße zu ändern. Im
Erfolgsfall lautet die neue Regel nun: .aStil { font-size:
3em; font-weight: bold; }
cssRule(".aStil@","color","red") um die Farbe (neu) zu setzen.
Im Erfolgsfall lautet die neue Regel nun also: .aStil { font-size:
2em; font-weight: bold; color: red; }
regel=cssRule(".aStil@print") um den Text
der (letzten) druckspezifischen (also in einem Printer-Stylesheet
befindlichen) Regel für die Klasse aStil auszulesen - also:
display: none;
regelObj=cssRule(".aStil@print","ruleobject")
um das diese Regel repräsentierende JavaScript-Objekt zu ermitteln.
Mit diesem Objekt kann man dann weitere Änderungen durchführen - z.B.:
cssRule(regelObj,"display","")
um die display-Eigenschaft zu löschen. Es gilt jetzt
der Default-Wert der display-Eigenschaft für die
betroffenen Elemente (d.h., das Element würde im Ausdruck erscheinen -
die Regel wäre jetzt leer).
if(!cssRule("body@print","font-size","12pt")) { addStyle("body { font-size: 12pt;","print"); }
versucht in einem Drucker-Stylesheet die Textgröße des Elements BODY auf
12pt zu ändern, und erstellt mittels addStyle()
ein neues Drucker-Stylesheet mit dieser Regel, falls keine existierende Regel
geändert werden konnte. Für diesen Zweck steht auch die Funktion setCssStyle()
zur Verfügung:
The function cssRule() offers a cross-browser compatible way
to read and change styles within style sheets (STYLE or LINK elements) (for
adding new style sheets or rules use addStyle()).
Although different browser incompatibilities do exist, it should be possible to
access wanted CSS rules and/or their styles within just by searching the sheets
with a given selector - even at definable media types (i.e. just to change the
style of an element for printer and not for screen output). In addition: It is
the only way to read & change pseudo formats (i.e. :hover).
The function call:
cssRule([target[,attribute[,value]]])
The 1st parameter target determines the wanted CSS rule. Possible
values are:
A string containing the wanted selector (case insensitive), i.e. p
for paragraph elements (<p>), #myId for
the element with ID myId (<p id="myId">),
.myClass for elements of the class myClass
(<p class="myClass">) etc.
In addition you can add a clipper to the selector to specify the style sheets
searched: selector@clipper. If the clipper is a digit, it will be
interpreted as the number of the wanted style sheet (i.e. .myClass@0
for searching the class selector myClass just in the 1st style sheet).
Otherwise the clipper will be interpreted as a media type, like it is been
used at the media attribute of the STYLE tag (i.e. .myClass@print
for accessing the rule of the class myClass which has to be in a
printer style sheet: <style type="text/css" media="print">).
With no media type or an * as media type given (i.e. .myClass
or .myClass@*), all style sheets will be searched (i.e.
<style type="text/css" media="print">,
<style type="text/css" media="screen"> &
<style type="text/css">). Adding an "empty"
media type (i.e. .myClass@) will take care that only
unspecified style sheets will be searched (<style type="text/css">).
The search is starting at the last rule of the last style sheet, going upwards,
ending with the first match.
Attention: Group selectors, i.e. p, div, pre { },
are also treated differently by the browsers (1 correct selector at Mozilla
since version 1.75, 3 separated ones at IE and 1 shortened to p
at Safari). So cssRule() can find the rule by giving each selector
of the group seperatly (of course: just the 1st at Safari =;-))!
A string with a pointer to the wanted rule "no. of style sheet/no. of rule"
starting with 0 (i.e. 0/0 for 1st style sheet/1st rule,
1/4 for 2nd style sheet/5th rule, etc.)
Attention: Avoid pre-defined pointers because of different browser
behaviour! Let cssRule() find out the pointer instead by using
the key word rulepointer as 2nd parameter (see below).
An object (more precisely: style object) which can be acquired with the
key word styleobject.
If no parameter is given, cssRule() will just test the browser
for the necessary functionality.
The real action is caused by the following (optional) parameters:
The 2nd parameter attribute is a string with the following meanings:
Give a CSS property and just the in the rule specified value of this
property will be handled. The allowed syntax is of CSS (font-size)
or JavaScript (fontSize) type (prefering CSS type because of,
you might guess it, browser incompatibilities - CSS: float /
IEs JScript: styleFloat / Mozillas JavaScript: cssFloat).
The 2nd parameter can contain a key word. At the moment these key words are:
rule (or an empty string or even no 2nd parameter at all)
for accessing the complete rule, exactly: the whole set of styles
of the rule according to the given selector.
sheetobject for retrieving JavaScript's styleSheet object
of the rule found.
sheetindex for retrieving style sheet's index number as an
integer. If no appropriate style sheet was found, NaN ("Not
a Number") will be returned instead of the usual false.
rulepointer for a (string) pointer of style sheet/rule -
as accepted as 1st parameter target. If access is prohibited,
an empty string will be returned instead of the usual false.
rulecollection for the entire collection of rules of the
style sheet found. With it you can cross-browser access this
collection, regardless whether the browser is using rules
(IE) or cssRules (other browsers). I.e. you can get the
number of rules by using length
(alert(cssRule("0/0","rulecollection").length)).
ruleobject for the JavaScript object of the rule itself, i.e.
to get the (internal) selector text used by the browser
(alert(cssRule("0/0","ruleobject").selectorText)).
styleobject for the JavaScript style object of the rule.
It accords to the syntax cssRule("0/0","ruleobject").style,
and can also be used as 1st parameter target.
ownerobject for the HTML object of the style sheet. I.e.:
use cssRule("0/0","ownerobject").tagName
to get the type of the style tag ("LINK" or "STYLE").
ownermarkup for the HTML markup of the style tag (which
also may be the browser's interpreted one).
Attention: Use a key word only if a selector or a pointer
(see rulepointer) is used as 1st parameter, not if a
rule's style object (see styleobject) was given! In the latter
case, cssRule() has direct access without searching or
"knowing" the style sheet.
Giving a 3rd parameter value changes the CSS text of the rule,
respectively the wanted property of the rule, to the given value. Examples: To
set the font size in the last occuring class selector "text" (regardless of
the media type) to "2em", write cssRule(".text","font-size","2em"),
to replace the CSS text of the latest rule with ID selector "head" at a printer
style sheet write cssRule("#head@print","rule","font-size: 2em; font-weight: bold;")
and to erase all the styles (not the rule itself) of that ID selector in a
style sheet for screen, write cssRule("#head@screen","rule","")
or shorter cssRule("#head@screen","","") - every time
returning true on success and false on failure.
Korrekturen: Beim letzten Update hatte sich ein Fehler eingeschlichen: W3C-DOM-Browser fanden/änderten auch Stile, wenn der Selektor, nicht aber der angegebene Medientyp paßte. Außerdem eine generelle Änderung: W3C-Browser haben (im Gegensatz zum IE) bei der Ermittlung des HTML-Quelltextes (Schlüsselwort: ownermarkup) von STYLE-Elementen mit dem verwendeten innerHTML bzw. outerHTML dynamische Änderungen nicht wiedergegeben. cssRule() ermittelt jetzt den tatsächlichen Quelltext komplett selbst.
04.08.2007:
Korrektur: Safari-2.x-Workaround eingebaut wg. Scriptabbruch wenn mediaText===null mit anschl. String-Methode (hier: mediaText.toLowerCase()).
05.07.2006:
Korrektur: Die Anpassung für IE/Mac (er kennt nicht nur das MS-typische rules-Objekt, sondern auch das offizielle cssRules-Objekt, jedoch ohne dessen Funktionalität) kollidierte mit dem Konqueror (bei dem es genau umgekehrt ist =:-)), was eine erneute Anpassung notwendig machte. Außerdem werden jetzt nicht nur im Selektor-Text einzeln auftretende "verhunzte" CLASS & ID-Selektoren korrigiert, sondern auch mehrfach auftretende.
01.07.2006:
Korrekturen & Erweiterung: Der Safari-Workaround funktionierte nicht mit Selektoren mit "-", und eine Anpassung für IE/Mac war notwendig. Neu hinzugekommen ist die Möglichkeit, Selektoren nur in einem speziellen Stylesheet suchen zu lassen (p@0 als target-Parameter für eine Suche nur im 1. Stylesheet).
28.06.2006:
Korrektur & Erweiterung: Hurra - 1. Workaround für Opera-Browser! Die Version 9 hat die notwendige Funktionalität jetzt ebenfalls. Da arbeitet man doch gerne um einen kleinen Browser-Bug (er meldet beim Zugriff auf ein nicht vorhandenes Stylesheet ggf. ein object statt undefined) herum ... ;-) Außerdem wurde ein Bug in der Attribut-Selektor-Entfernung des Safari-Workarounds behoben und die Routine verfeinert: es werden nur noch exakt die Attribut-Selektoren entfernt, die überflüssig sind. Interne Änderung: Das Umwandeln der Style-Schreibweise von CSS- auf JS-Syntax wurde in eine separate Funktion ausgelagert.
22.06.2006:
Erweiterung: Neue Schlüsselwörter hinzugefügt (sheetindex, rulepointer, rulecollection, ruleobject, ownerobject und ownermarkup).
17.06.2006:
Korrekturen: Fehler bei Verwendung von Gruppen-Selektoren in Mozilla >= 1.75 behoben (war der Selektor einer Regel nochmals in einer Gruppe aufgeührt, dann wurde die Suche nicht beim Gruppen-Selektor abgebrochen). Außerdem werden jetzt automatisch eventuell vorhandene Attribut-Selektoren [CLASS~="..."] & [ID"..."] aus dem Selektor-Text entfernt (sie werden beim Safari eigenmächtig hinzufügt, und verhinderten die erfolgreiche Suche nach Klassen- & ID-Selektoren in "normaler" Schreibweise).
26.05.2006:
Erweiterung: Stylesheets können nach Medientyp unterschieden werden, Stylesheet-Objekt ist ermittelbar und Fehler beim illegalen Zugriff auf externe Stylesheets von fremden Servern werden abgefangen.