Es gibt eine globale Menu-Vorlage, aus der verschiedene Anzeigetypen generiert werden können:
z.B.
- Die Vorlage für ein JavaScript-Menu mit leckeren DHTML-Effekten.
- Die spartanische Variante für fanatische Links-/Lynx-/Telnetsurfer.
- Eine Flash-Variante, wenn man seinen Content in Flash komplett aus der Datenbank holt.
- Um daraus XML zu erzeugen, ob es nun nur cool ist oder tatsächlich einen Sinn erfüllt.
- Um PDFs davon machen zu können, obwohl ich nicht weiß, wer so etwas braucht...
- Wenn man einmal angefangen hat, ein Content Management System aufzusetzen und
sich überlegt hat, das selbst zu schreiben und nicht irgendeine fertige
Lösung aus der Dose zu nehmen - auf freshmeat.net gibt es dazu genug Quellen -,
ist ein dynamisches Menü der erste - vielleicht sogar der wichtigste - Schritt.
BTW: Ich wollte den Leuten, die fertige CMS benutzen, nicht auf die Füße treten,
aber diese Text richtet sich auch schließlich nicht an sie.
- Das Menü wird über ein Web-Frontend konfigurierbar, sehr angenehm, wenn
man mal eben eine Kategorie / einen Menüpunkt hinzufügen will und gerade
die ganzen Files nicht zu Hand hat.
- Man kann auf diese Weise DAU-feste Interfaces schreiben, mit denen wirklich (fast)
jeder in der Lage ist, ein anständig aussehendes Menü zu aktualisieren
- und und und...
Unterstützte Browser
Für die JavaScript-Anzeige:
- MS Internet Explorer ab Version 4 denke ich mal, ab IE5 mit Sicherheit (getestet).
- Netscape 4.7 (getestet)
- Netscape 6.x (getestet)
- Konqueror (getestet)
Für die HTML-Version:
- natürlich alle der obigen Browser
- ALLE anderen Browser, die HTML anzeigen: Links, Lynx, w3m inclusive!
Warum die Arbeit?
man lernt dabei mit PHP und SQL umzugehen.
Wenn man das einmal aufgesetzt hat und es läuft, spart man
sich für die Zukunft eine Menge Arbeit und mögliche Fehlerquellen.
Konkret: Der JS-Ansatz
Ich werde hier nicht auf die JavaScript-Einzelheiten eingehen, weil ich mich
(a) nicht besonders gut damit auskenne und weil sie
(b) für diesen Artikel nur eine nebensächliche Rolle
spielen.
Wir haben also eins diese JS-Menüs, die man z.B. von http://www.dynamicdrive.com ziehen kann.
Um ganz genau zu sein, habe ich folgendes Script, mit einigen Modifikationen benutzt:
http://www.dynamicdrive.com/dynamicindex1/topnavbar.htm.
Was dieser Art von Menüs in der Regel gemeinsam ist, ist die Struktur des Files, in dem die Menüpunkte
festgelegt werden.
Erst mal kommt eine Reihe von Variablen, mit denen man das Aussehen des Menüs einstellen kann;
z.B. Text-/Hintergrundfarbe, Font usw.
In meinem Beispiel:
var NoOffFirstLineMenus=4; // Number of first level items
var LowBgColor='black'; // Background color when mouse is not over
var LowSubBgColor='black'; // Background color when mouse is not over on subs
var HighBgColor='black'; // Background color when mouse is over
var HighSubBgColor='black'; // Background color when mouse is over on subs
var FontLowColor='white'; // Font color when mouse is not over
var FontSubLowColor='white'; // Font color subs when mouse is not over
var FontHighColor='white'; // Font color when mouse is over
var FontSubHighColor='white'; // Font color subs when mouse is over
var BorderColor='white'; // Border color
var BorderSubColor='white'; // Border color for subs
var BorderWidth=1; // Border width
var BorderBtwnElmnts=1; // Border between elements 1 or 0
var FontFamily="arial,comic sans ms,technical"; // Font family menu items
var FontSize=9; // Font size menu items
var FontBold=1; // Bold menu items 1 or 0
var FontItalic=0; // Italic menu items 1 or 0
[...]
|
Auszug aus dem Config-File des JS-Menüs
Danach werden in diesem Beispiel noch vier Basisfunktionen definiert, die nicht wirklich viel machen.
function BeforeStart(){return}
function AfterBuild(){return}
function BeforeFirstOpen(){return}
function AfterCloseAll(){return}
|
die Funktionen
Das war es auch schon mit den Vorbereitungen. Das JS-Menü erwartet die Menüeinträge als
in der folgenden Form:
1: Menu1=new Array("void main(...)","http://www.manuelm.org","",4,20,150);
2: Menu1_1=new Array("long Lebenslauf","?content=lebenslauf","",0,20,150);
3: Menu1_2=new Array("unsigned long Studium","?content=studium/studium&menu=yes","",0);
4: Menu1_3=new Array("Flash-Präsentation","http://www.manuelm.org","",0);
5: Menu1_4=new Array("char News","?content=news&menu=yes","",0);
6:
7: Menu2=new Array("char projekte(...)","http://www.manuelm.org","",6,20,125);
8: Menu2_1=new Array("Linux","?content=linux/main&menu=yes","",0,20,125);
9: Menu2_2=new Array("Kaffee-Maschine","?content=coffee/main&menu=yes","",0);
10: Menu2_3=new Array("Hitcounter","?content=stats/main&menu=yes","",0);
11: Menu2_4=new Array("Flash Spielereien","?content=portrait/main","",0);
13: Menu2_5=new Array("WAP","?content=linux/wap&menu=yes","",0);
14: Menu2_6=new Array("iKnow","?content=linux/iknow&menu=yes","",0);
15: [...]
|
Menüarrays
Schritt für Schritt:
1: Menu1=new Array("#angezeigter Menuname#","#link#","",#Anzahl Submenus#,#Hoehe#,#Breite#);
|
Menü 1
Hier wird der erste Menüeintrag (deshalb Menu1) definiert, er ist gleichzeitig
die Kategorie, also der Name des Menüs, der oben ganz links angezeigt wird.
Anschießend kommen fünf wichtige Felder, in die ich hier mal die Bedeutung hineingeschrieben habe.
Das sollte soweit selbsterklärend sein.
Die Anzahle der Submenüs ist einfach die Anzahl der Einträge, die im Menü sind,
die wird automatisch vom PHP-Script generiert werden.
Analog wird die zweite Kategorie in Zeile 7 festgelegt. Die Leerzeile und die Einrückungen sind natürlich
nicht nötig.
2: Menu1_1=new Array("Menu1 erster Menupunkt","http://www.foobar.com/der_link_dazu.html","",0,20,150);
|
Menü 1, Menüpunkt 1
In den Zeilen 2-5 werden jetzt nur noch die Menüeinträge festgelegt, analog für das zweite Menü
in den Zeilen 8-14.
Das solls mit JavaScript erstmal gewesen sein, jetzt kommt der SQL-Teil
Die Struktur in der Datenbank
Bemerkung vorweg: bei mir heißt Menunamenummer topid und Menueintragsnummer entryid
In der Datenbank gibt es eine Tabelle, in der Menünamen und -punkte stehen.
Sie sieht etwa so aus:
| topid | entryid | Menüeintrag | Link |
| 1 | 0 | void main(...) | http://www.manuelm.org |
| 1 | 1 | long Lebenslauf | ?content=lebenslauf" |
Auszug aus der SQL-Menütabelle
Die SQL-Querys, um eine solche Tabelle zu erstellen, sehen folgendermaßen aus:
CREATE TABLE menu (
topid tinyint(4) DEFAULT '0' NOT NULL,
entryid tinyint(4) DEFAULT '0' NOT NULL,
content text NOT NULL,
link text NOT NULL
);
|
SQL-Befehle für Menu-Table
Das PHP-Script
Fehlt also nur noch das Script, mit dem die Arrays für das JavaScript-Menü
erzeugt werden. Die ganzen Variablen können einfach so aus einer statischen Textdatei
mit include() geholt werden.
Dann sollte man den Link zur Datenbank mal aufmachen:
1: $host = >dbhost<
2: $user = >dbuser<
3: $password = >dbpwd<
4: $db = >your database<
5: $menutable = >name of table with menu entries<
6: $link = mysql_connect ($host, $user, $password)
7: or exit(-1);
|
Link zur DB aufmachen
Wichtig ist, daß das Script erstmal erkennen muß, wie viele Einträge es unter einer Kategorie gibt,
schließlich muß das ja angegeben werden. Die ganze Tabelle wird deshalb für jedes Menü durchiteriert,
wobei ich davon ausgehe, daß es unter einer Kategorie nur Menüpunkte gibt und nicht auch noch Unterkategorien,
was das JS hergibt, mich aber nicht interessiert hat.
Erstmal das Script im Überblick:
0: [...]
1: $query = "SELECT max(topid) FROM menu";
2:
3: $result = mysql_db_query($db,$query)
4: or die("Fehler beim SELECT: $query");
6:
7: $row2=mysql_fetch_array($result);
8:
9: for ($i=1;$i<($row2[0]+1);$i++)
10: {
11: $query ="SELECT * FROM $menutable WHERE (topid = "\".$i."\") ORDER by entryid";
12: $result = mysql_db_query($db,$query)
13: or die("Fehler beim SELECT2:$query");
14: while ($row = mysql_fetch_array($result))
15: {
16: if ($row['entryid'] == 0)
17: {
18: /* Menu-Name */
19: $query2 ="SELECT topid FROM $menutable WHERE (topid = \"".$i."\")";
20: $num_entries = mysql_num_rows(mysql_db_query($db,$query2))
21: or die("Fehler beim SELECT: $query");
22: echo "\nMenu".$i."=new Array(\"".$row['content']."\",\"".$row['link'].
"&menu=1\",\"\",".($num_entries - 1).",20,150);\n";
23: }
24: else
25: {
26: /* Menu-Einträge */
27: echo "Menu".$i."_".$row['entryid']."=new Array(\"".$row['content']."\
",\"".$row['link']."&menu=1\",\"\",0,20,150);\n";
28: }
29: }
30: }
31: [...]
");
|
Der Algorithmus, um das Menü zu erzeugen
Vorher mache ich natürlich noch die Verbindung zur Datenbank auf. Das vollständige Script stelle ich unten bei den Links zur Verfügung.
Was dieser Teil macht:
Der Query, der die Anzahl von Kategorien zurückliefert:
1: $query = "SELECT max(topid) FROM menu";
|
Hier wird der Query ausführt, und das Ergebnis geholt:
3: $result = mysql_db_query($db,$query)
4: or die("Fehler beim SELECT: $query");
6:
7: $row2=mysql_fetch_array($result);
|
Jetzt startet die erste Schleife, die die Kategorien durchiteriert:
9: for ($i=1;$i<($row2[0]+1);$i++)
|
In $row2[0] steht die Anzahl der Kategorien drin, die wir eben geholt haben.
Nun die Kategorienamen holen. Sie sind dadurch definiert, daß ihre EntryID == 0 ist (Zeile 16):
11: $query ="SELECT * FROM $menutable WHERE (topid = \"".$i."\") ORDER by entryid";
12: $result = mysql_db_query($db,$query)
13: or die("Fehler beim SELECT2:$query");
14: while ($row = mysql_fetch_array($result))
15: {
16: if ($row['entryid'] == 0)
17: {
18: /* Menu-Name */
19: $query2 ="SELECT topid FROM $menutable WHERE (topid = \"".$i."\")";
20: $num_entries = mysql_num_rows(mysql_db_query($db,$query2))
21: or die("Fehler beim SELECT: $query");
22: echo "\nMenu".$i."=new Array(\"".$row['content']."\",\"".$row['link'].
"&menu=1\",\"\",".($num_entries - 1).",20,150);\n";
23: }
|
Wenn die EntryID != 0 ist, muß es ein Menüeintrag sein, er wird über die TopID dem jeweiligen Menü zugeordnet:
24: else
25: {
26: /* Menu-Einträge */
27: echo "Menu".$i."_".$row['entryid']."=new Array(\"".$row['content']."\",\"
".$row['link']."&menu=1\",\"\",0,20,150);\n";
28: }
|
wieder nur billiges iteratives "Abgrasen" der Einträge!
Wie leicht zu erkennen ist, sind bei mir Breite und Höhe der Menüfelder immer fest auf 20 bzw. 150 Pixel eingestellt.
Wer will, kann auch das noch als Feld in der Datenbank speichern. Bei mir sind alle Menüfelder gleich groß.
Das war es schon fast!
Ein paar Sachen fehlen aber noch:
1.: Script-Header:
echo "<script type=\"text/javascript\">\n";
echo " function Go(){return}\n";
echo "</script>\n";
|
2.: Die Variablen müssen ja noch aus dem statischen File inkludiert werden (s.o):
include('js/variables.js');
bei mir liegt das File offensichtlich im Verzeichnis js/"
Schmankerl: HTML-Version für deaktiviertes JS
Bis jetzt hat das ganze ja eigentlich nur Arbeit gemacht. Jetzt kommt ein Teil, der Arbeit erspart.
Da die Menüstruktur ohnehin unabhängig von der Formatierung vorliegt, läßt sich jetzt mühelos eine pure HTML-Version daraus erstellen. Ich habe hier als Beispiel mal die genommen,
die ich auf meiner Seite einsetze.
Wie man das HTML-Menü nun aber formatiert, bleibt jedem selbst überlassen.
Hier also der Quellcode meiner Version:
1: //Textmenu
2: $link = mysql_connect ($host, $user, $password)
3: or exit(-1);
4: $query = "SELECT max(topid) FROM menu";
5: $result = mysql_db_query($db,$query)
6: or die("Fehler beim SELECT1: <b>$query</b>");
7: $row2=mysql_fetch_array($result);
8: echo "<center><table border=\\"0\\"><tr>\n";
9: for ($i=1;$i<($row2[0]+1);$i++)
10: {
11: $query ="SELECT * FROM $menutable WHERE (topid = \"".$i."\") ORDER by entryid";
12: $result = mysql_db_query($db,$query)
13: or die("Fehler beim SELECT: $query");
14: echo "<td valign=\"top\">\n";
15: while ($row = mysql_fetch_array($result))
16: {
17: if ($row['entryid'] == 0)
18: {
19: //Menu-Name
20: $query2 ="SELECT topid FROM $menutable WHERE (topid = \"".$i."\")";
21: $num_entries = mysql_num_rows(mysql_db_query($db,$query2))
22: or die("Fehler beim SELECT: <b>$query</b>");
23: echo "<b><a href=\"".$row['link']."\">".$row['content']."</a></b><br>\n";
24: }
25: else
26: {
27: //Menu-Einträge
28: echo "<a href=\"".$row['link']."\">".$row['content']."</a><br>\n";
29: }
30: }
31: echo "</td>\n";
32: }
33: echo "</tr>\n</table></center>\n";
Scriptabschnitt für die HTML-Version
In diesen Zeilen passiert praktisch das gleiche, wie in den vorher eingehend beschriebenen für die Erzeugung der JavaScript-Arrays, nur daß diesmal die gleichen Informationen als HTML
formatiert ausgegeben werden.
Erweiterungen
Wie in der Einleitung angedeutet, ist auch es auf diese Weise leicht, aus dem Tabelleninhalt XML zu erzeugen und umgekehrt.
Auch WML geht, zumal man da gleich die Links auf die passenden Decks setzen kann.
Den Kram in ein Flashmenü zu packen geht jetzt auch einfach, entweder über den XML-"Umweg" oder direkt.
Wenn man ohnehin erfaßt, ob die Clients der Seite JS aktiviert haben, kann man ihnen "automagisch" die HTML-Alternative geben.
Ein Frontend zu programmieren, ist jetzt auch kein Problem mehr. Realisieren könnte man das in PHP, um das Menü im Browser ändern zu können, aber auch eine Variante, die direkt
auf die DB zugreift - wenn der Provider das erlaubt - ist möglich.
Quellcode
Hier habe ich die Dateien nochmal zum Download zusammengestellt:
das JS-File mit den statischen Variablen: variables.js
das PHP-Script, daß die ganze Arbeit macht: creator.phps
das JS-File mit dem eigentlichen Menü: menu.js
das Script, um die Tabelle für die Menüeinträge zu erstellen: menu.sql
die Tabelle erstellt man dann einfach mit mysql -p Username < menu.sql
Zip mit allem, was man braucht
Links
http://www.dynamicdrive.com, dort gibt es Massen von JS
http://www.dynamicdrive.com/dynamicindex1/topnavbar.htm, auch diese Menü könnte man nehmen
The PHP Layers Menu: es gibt Leute, die das wesentlich perfekter umgesetzt haben!
working demo: als Beispiel, wie das aussehen kann
Impressum
Der Verfasser übernimmt keine Haftung für irgendwelche Aktionen, die durch diesen Text ausgelöst werden.
Vervielfältigung & Verbreitung einer veränderten Version nur mit ausdrücklicher Erlaubnis des Verfassers.
Änderungen vorbehalten.
(c) 2002 by Manuel Möller, mailto:contact@manuelm.org, http://www.manuelm.org