Styles
(CSS) zur
Gestaltung interaktiver Websites
Normaler Weise verwenden und erstellen gute Editoren
Stylesheets automatisch. Man muß sich also nicht unbedingt damit befassen. Eine
für den Programmierer interessante Einsatzmöglichkeit ist aber, die Tags über die Einbindung des Style-Parameters in ihren Gestaltungs- und Positionierungsmöglichkeiten zu erweitern, und auf alle diese Einstellungen dann dynamisch über JavaScript zugreifen zu können.
Ein Beispiel sagt mehr, als 1000 Worte:
<div id="einDiv"
style="background:einBild.jpg; position:absolute; left:100px;
top:100px">
Was passiert da? Über den Style-Parameter können jetzt
alle Gestaltungsmöglichkeiten eines Style-Sheets diesem Absatz (div) zugeordnet
werden, besonders interessant natürlich für jene Parameter, die normalerweise im DIV-Tag nicht zur Verfügung stehen,
als da sind Hintergrundbild und absolute Positionierung. Gerade die begrenzte Positionierbarkeit war ja ein großes Manko von HTML. Für ein wirklich professionelles Layout muß man einzelne Elemente pixelgenau positionieren können.
Es kommt aber noch besser: Über das style-Objekt kann
man von JavaScript aus dynamisch auf diese Parameter zugreifen, und sie
interaktiv verändern. (Kleiner Wermutstropfen: Der Netscape kann dies erst seit
der Version 6) Zuerst aber möchte ich die Syntax des style-Parameters
erläutern:
Eingebunden wird er in der normalen HTML-Syntax, d. h.
Leerzeichen, Parametername, Gleichheitszeichen, Wert in Anführungsstrichen:
<div style="">.
Für die einzelnen style-Parameter gilt dann aber die
Style-Syntax, d. h. Trennung durch Semikolon und Doppelpunkt zwischen
Parametername und Wert. Ein bißchen kompliziert, aber zu bewältigen. Schaut es
Euch oben noch mal an!
Ein Punkt wird dem aufmerksamen Beobachter noch aufgefallen
sein. "position:absolute". Das ist eigentlich ganz einfach: Es wird die absolute
Pixelposition, die mit den Parametern "left" und "top" festgelegt wurde
eingenommen.
Verwendet man dagegen "position:relative", so wird das
Tag, ausgehend von der Position die es als normales HTML-Element einnehmen würde
(also schön eins nach dem anderen, plus Zeilenumbrüche <br> und Absätze
<p>), relativ verschoben. So könnte man z. B. eine Einrückung
realisieren, während sich die vertikale Position aus dem Textfluß ergibt.
Wie greift man jetzt mit JavaScript auf diese Style-Parameter zu?
Über das style-Objekt des Tags, also, man nehme die id = einDiv und greife
über den Punkt-Operator (hochtrabender Begriff, man könnte auich einfach sagen
Trennpunkt zwischen Ober- und Unterobjekt) auf das style-Objekt und seine
Parameter zu:
einDiv.style.left = "100px";
Okay, ganz so einfach ist es dann doch nicht. Da sich
die Programmierer von Netscape und Microsoft irgendwie nicht einigen können, muß
man beim I-Explorer "pixLeft" verwenden, beim Netscape6 dagegen einfach "left"
(was ja auch viel richtiger ist), und beim Netscape 4 wiederum direkt "einDiv.left",
da diesem das style-Objekt unbekannt ist (in Sachen DHTML war Netscape
Spätzünder).
Wenn style-Parameter Doppelnamen sind, z. B.
"font-size", wird in JavaScript (wo Trennstriche nicht erlaubt sind) folgende
Schreibweise verwendet: "fontSize". Wichtig ist die exakte Groß- und
Kleinschreibung, sonst geht nichts.
Das alles nur zur Einführung, die es erlaubt, meine
praktischen Beispiele und Scripte zu studieren und analysieren. Denn wie gesagt, oft sind Fallunterscheidungen zwischen
Netscape und I-Explorer notwendig, und alle Parameter kann man sich natürlich
als Einsteiger auch nicht gleich aus den Fingern
saugen. Wichtig ist nur, daß man das Prinzip verstanden hat. Mit diesem
Grundsätzlichen Rüstzeug kann man analysieren und verstehen, was andere gemacht haben.
Hier ein
Beispiel , wie oben erläuterte
Prinzipien zur pixelgenauen Positionierung eines Bildes verwendet werden können:
<img src="einBild.gif"
style="position:absolute; top:50px; left:30%">
Das Bild wird im linken Drittel der Seite, 50 Pixel vom
oberen Rand entfernt platziert. Läßt man den "left"-Parameter weg, und verwendet
stattdessen <center>-Tags oder den klassischen align-Parameter
(align="center"), wird das Bild in der Seitenmitte positioniert, aber wie gehabt
mit einem Abstand von 50 Pixel vom oberen Rand.
Eine Animation mit dem Style-Parameter.(in Vorbereitung)
Ausführliche Infos zu CSS auf der
W3C-Seite .
Die zugrunde liegende Idee ist, Programme aus Bausteinen zusammenzusetzen.
Dadurch können einzelne Standard-Bausteine immer wieder verwendet werden (was
die Entwicklungszeiten erheblich verkürzt), andere Bausteine können gezielt,
selektiv und übersichtlich weiterentwickelt werden (die Wartung und
Weiterentwicklung von Programmen wird also erheblich vereinfacht) und es ist
möglich, die Arbeit an einem Programm an ein Team, vielleicht sogar viele Teams,
die sich jeweils mit Details beschäftigen, zu vergeben.
Es gibt unterschiedliche (im Kern aber ähnliche) Ansätze, dieses
Bausteinprinzip zu realisieren. Einer davon sind die ActiveX-Komponenten von
Microsoft. Der flexibelste Ansatz ist die objektorientierte Programmierung. Hier
einige Grundbegriffe:
Ein Objekt ist die Instanz einer Klasse. Klingt furchtbar abstrakt, ist
aber ganz einfach: Die Klasse ist die Definition des Erbmaterials des Objektes,
in Form von Programmcode. Alle Objekte die von einer Klasse instanziert werden,
sind Klone. Die Klasse selber ist gar nichts, bzw. eben nur das
Erbmaterial.
Wie sieht solcher Klassen-Programmcode aus, der ein
Objekt definiert, bzw. aus dem Objekte instanziert werden können? Es handelt
sich im Prinzip einfach um eine Sammlung von Variablen und Funktionen. Man
spricht auch von den Eigenschaften (die Variablen, die bestimmte Daten und Werte
speichern) und Methoden (die Fähigkeiten des Objektes, bestimmte
Dienstleistungen zu verrichten, z. B. eine Suchfunktion, die Berechnung eines
Wertes usw.)
[erläuterndes Beispiel]
Es gibt jetzt sehr einfache Objekte (Klassen), die nur ein paar
Variablen enthalten, und vielleicht eine einfache Funktion, die diese Variablen auf
Anfrage zurückgibt, aber es gibt auch sehr komplexe Objekte, die sehr
komplexe Aufgaben erledigen, wie z. B. die Wiedergabe von Multimedia-Dateien.
Durch die Zusammenfassung ihrer Eigenschaften und Methoden in einer Klasse kann
man immer wieder, wann und wo man es braucht, beliebig viele Instanzen bilden,
und dann auf deren Fähigkeiten zugreifen. Das machten den Programmcode kürzer
und übersichtlicher, und verkürzt natürlich auch die Entwicklungszeit.
Ganz wichtig in diesem Zusammenhang ist die
Objekt-Kapselung, das heißt der Schutz der Objektvariablen vor Zugriffen von
außen (von anderen Objekten und Programmen.). Alle Methoden und Eigenschaften
einer Objektinstanz können automatisch (man muß sich um die Kapselung nicht
besonders kümmern) nur über die vorhergehende Nennung des Objektes angesprochen werden, und nur
dort, wo auch das Objekt bekannt ist (instanziert wurde). Ein Objekt,
das innerhalb eines größeren Objektes instanziert wurde, kann nur von diesem
übergeordneten Objekt angesprochen werden. Ein Objekt innerhalb eines Programmes kann
nur von diesem Programm angesprochen werden, und nicht von außen von
anderen Programmen. Auf diese Weise können unerlaubte Zugriffe und ungewollte und unvorhersehbare gegenseitige
Beeinflussungen von Objekten vermieden werden, was mit zunehmender Komplexität von Programmen
und deren Objekt- und Variablenstruktur immer wichtiger wird.
Die Syntax objektorientierter Programmierung ist natürlich
Programmiersprachen-abhängig. Es gibt aber einige Gemeinsamkeiten bei den
meisten Sprachen:
- eine Instanz einer Klasse wird mit dem New-Operator
gebildet. z. B. einObjekt = new
eineKlasse, wobei einObjekt der Name des instanzierten Objektes
ist, eineKlasse der Name der zugrundeliegenden Klasse.
- auf die Variablen und Funktionen eines Objektes wird meist mit dem
Punkt-Operator zugegriffen:
einObjekt.eineVariable = einWert oder
einWert =
einObjekt.eineFunktion()
Ein sehr spezielles (obwohl kaum eingesetztes) Leistungsmerkmal von
JavaScript ist dessen Objektorientiertheit. Da sie sich hinter der simplen
Functions-Syntax versteckt, ist sie vielen gar nicht bewußt, und auch selten
oder schlecht dokumentiert.
Ich will in den folgenden Zeilen aufzeigen, wie man auf
einfache Weise diese Objektorientiertheit in seinen Scripten einsetzen und zum
Vorteil nutzen kann.
Warum überhaupt objektorientiert
programmieren?
Gute Frage, nächste Frage. Oder Antwort: Weil es geht.
Okay, da eines der wichtigsten Features objektorientierter Programmierung in
JavaScript fehlt, nämlich die
Kapselung (s. o.), können Objekte eigentlich nur
die Verwaltung von Daten-Strukturen, insbesondere hierarchisch geordneten,
übersichtlicher machen.
[kurze
Erläuterung]
Das ist aber bereits ein
interessanter Vorteil, und so ganz nebenbei lernt man die Prinzipien
objektorientierten Programmierens kennen und anwenden.
Was ich mit Daten-Strukturierung
meine, läßt sich nur am Beispiel wirklich anschaulich zeigen:
function Person(name, alter) {
this.name =
name; // Eigenschaften der Person
this.alter =
alter;
this.gruss =
personGruss; } // Methode (Fähigkeit) der Person
}
function personGruss() {
var msg =
‘Hallo, ich bin der ‘ + this.name;
alert(msg);
}
Ebenso simpel wie trotzdem verwirrend: In JavaScript werden Objekte mit der Funktions-Syntax
definiert. Ziemlich blöd und nicht gekapselt, aber ist halt so
(Gruß an Netscape: toll gemacht!)
Die Funktion "einePerson" ist also unsere Objektklasse,
bzw. gleichzeitig deren Konstruktor (was Java-Programmierern etwas sagt). Machen
wir da mal eine Objekt-Instanz draus, und übergeben gleichzeitig (als
Funktions-Parameter) die Eigenschaften dieses Objektes, nämlich Name und
Alter:
Pete = new Person("Pete", 35);
Mit dem Schlüsselwort "this" sowie dem Punktoperator werden diese Parameter
dem Objekt als Eigenschaften übergeben, und können dann über den
Eigenschaften-Namen verändert oder abgerufen werden:
var name = Pete.name;
Pete.alter = Pete.alter + 1; // Pete hatte
Geburtstag
Etwas anders verhält es sich mit der Methode von Pete. Seine Fähigkeit zu
grüßen. Sie wird extern (als Funktion) definiert, und dann über den Functions-Namen und
das "this"-Schlüsselwort dem Objekt implementiert. Wichtig ist hierbei: Würde
man die Klammern hinter dem Funktionsnamen anfügen, also
this.gruss = personGruss();
so würde die Funktion automatisch beim Instanzieren (Erschaffen)
des Objektes (der Person) aufgerufen. Das macht Sinn für konfigurierende
Methoden (Methoden die grundsätzliche Eigenschaften festlegen) aber der Gruß
sollte natürlich nur erfolgen, wenn es auch jemand zu grüßen gibt. Die
Grußmethode wird dann folgendermaßen aufgerufen:
Pete.gruss();
Das war's eigentlich schon mit diesem einfachen Objekt. Richtig
interessant wird es jetzt, wenn dieses Objekt wiederum Eigenschaft (und damit
Teil) einer Gruppe wird. Dann kommen wir schon in den Bereich hierarchisch
strukturierter Daten. z. B. könnten mehrere Personen der Gruppe der Angestellten
eines Unternehmens zugeordnet werden. Oder wir erschaffen ein hierarchisches
Menu mit Untereinträgen und Verzweigungen. Fangen wir mal ganz langsam an:
function Gruppe(name) {
this.name =
name;
this.add = personAdd;
}
function personAdd(name, alter) {
this[name] = new
Person(name, alter)
}
Wir kreieren jetzt also eine Gruppe, nehmen wir mal die Gruppe
der Freaks:
Freaks = new Gruppe("Freaks");
Freaks.add("Pete", 35);
Freaks.add("Bolle", 25);
Über die Add-Methode der Gruppe wurden gleich zwei Mitglieder,
jeweils mit Name und Alter, hinzugefügt. Erwähnenswert ist hierbei, daß die
Personen nachträglich, in beliebiger Anzahl hinzugefügt werden können, und daß
diese Personen zugleich Eigenschaften wie auch Unterobjekte von Gruppe sind.
Neben Variablen können also auch Objekte Eigenschaften von Objekten sein. Das
gibt einem die Möglichkeit zu beliebig tief gehender, hierarchischer
Strukturierung. Jedes Objekt kann weitere Unter- oder Ober-Objekte
besitzen.
Ein Mitglied der Freaks grüßt jetzt
folgendermaßen:
Freaks.Bolle.gruss();
Die von dieser Funktion ausgegebene Meldung wäre: "Hallo, ich
bin der Bolle."
Mit folgendem "Kniff" erreicht man eine
automatische Indizierung (Zugriffsschlüssel) neu hinzugefügter Objekte:
function Autos() { // die
Gruppe
this.laenge = 0;
this.letzter =
this[this.laenge];
this.add = addAuto;
}
function addAuto(typ,
tueren, PS) {
this.laenge++;
this[this.laenge] = new Auto(typ, tueren, PS);
}
function Auto(typ, tueren, PS)
{ // Gruppenmitglied
this.typ = typ;
this.tueren = tueren;
this.PS = PS;
}
Die Objekt-Instanzen von Auto speichern die Daten
der einzelnen Autos. Interessant ist jetzt, daß sie hier keinen Namen haben,
sondern unter laufender Nummerierung der Gruppe "Autos" zugeordnet werden.
Die add-Methode der Gruppe erhöht die laenge-Eigenschaft der Gruppe, und kreiert
dann einen Eintrag mit den übergebenen Daten, der unter der zuvor erhöhten
laufenden Nummer (laenge) eingeordnet wird. Den jeweils letzten Eintrag kann man
über die Eigenschaft "letzter" der Gruppe abrufen. Nach diesem Vorbild können
beliebig tief gestaffelte Datenobjekte erschaffen werden, die intern eine
automatische Nummerierung (Indizierung) der zugeordneten Objekte vornehmen. In
der Programmierpraxis nennt man das "Collection".
DHTML-Objekte zur
Laufzeit:
Ab Java 1.3 (Umgesetzt ab Internet-Explorer 5 und Netscape 6 - Netscape 4
könnt ihr in die Tonne kloppen) gibt es auch die Möglichkeit,
DHTML-Objekte zur Laufzeit zu kreieren, und als Tags in
das Document einzufügen. Das ist sehr praktisch, funktioniert
aber noch nicht bei allen Browsern:
var einObjekt =
document.createElement("DIV");
einObjekt.id =
"dynAbsatz";
einObjekt.style.position = "absolute";
einObjekt.style.left =
"100px";
einObjekt.style.top =
"100px";
document.body.appendChild(einObjekt);
Hier wurde in JavaScript ein DHTML-Objekt geschaffen, und
zwar ein Absatz mit folgendem Tag:
<div id="dynAbsatz"
style="position:absolute; left=100px; top=100px"></div>
Es können beliebig
viele solcher Absätze zur Laufzeit geschaffen, sowie dynamisch in
Position und Inhalt (usw.) verändert werden. Ein Zugriff
mit JavaScript könnte folgender Maßen aussehen:
einObjekt.innerHTML =
"Ich werde gleich verrückt!";
einObjekt.style.left =
"200px";
Auch dieser Absatz kann wieder Unterabsätze
und Unterobjekte enthalten, wobei die oben angeführten Objekt-Prinzipien zur
Verfügung stehen. Aufeinmal wird verständlich, was bei diversen Scripten mit
hierarchischen Menus oder Verzeichnissen passiert! Das hier (links) verwendete
Menu basiert vollständig auf diesem Prinzip (
HierMenus
). Als theoretische Grundlage
soll das reichen. Die praktische Anwendung und Umsetzung studiert man am besten
in fertigen Scripten, wie man überhaupt das Programmieren nur durch Studium von
Programmen und selber programmieren lernen kann. [siehe
Links ]. Bei Interesse werde ich diese
Einführung um kommentierte Beispiele zum downloaden
ergänzen.
Die aus meiner Sicht ultimative und erschöpfende Seite zum Thema Suchmaschinen
und Metatags ist
Metaman. Hier nur ein
kurzer Abriss:
Viele Leute glauben, sie
müßten nur ein paar Meta-Tags mit Keywords in ihre Page einfügen, und schon
werden sie durch die diversen Suchmaschinen im Netz gefunden. Weit
gefehlt:
-
ihr müßt Euch anmelden. Das Netz ist viel zu
groß geworden, als daß man sich darauf verlassen könnte, zufällig von
stöbernden Suchmaschinen erfaßt zu werden. Also: Hauptseite der jeweiligen
Suchmaschine aufsuchen, Link zum URL-Anmelden suchen, Homepage-URL
eingeben.
-
Eure Keywords müssen auch im Text Eurer Seite vorkommen. Es
nützt nichts, wenn sie zwar den Inhalt beschreiben, von den Robots dann aber
nicht im Text gefunden werden. Noch schlimmer ist, wenn sie gar keinen Bezug
zum Text haben, dann seid ihr ganz schnell auf dem Index für böse Jungs
(Mädchen).
-
Viele Suchmaschinen haben die Möglichkeit zum Anmelden bereits
abgeschafft, weil sie der Masse nicht mehr Herr werden. Andere, wie z. B.
Yahoo, nehmen eine Seite ohnehin nur nach redaktioneller Überprüfung auf, d.
h. Metatags sind unerheblich, und die Chancen für simple Homepages sehr
gering.
Gerade kleinere, private Homepages sollten
deshalb, zusätzlich zu den Metatags, Möglichkeiten des Zusammenschlusses in
Clubs (z. B. die Yahoo- oder Planetinternet -Clubs), oder ein Webring, um auf diese Weise ihre Seite zu promoten und Gleichgesinnte zu finden.