Tipps zu PHP
Hier stelle ich konkrete und überschaubare Aufgaben und ihre Lösung per PHP vor.
Die Seite richtet sich in erster Linie an Web-Autoren ohne Programmierkenntnisse, die ihren Dokumenten einige Extras hinzufügen möchten.
In der Rubrik Gesuchte Skripte skizziere ich Aufgaben, für die ich noch eine Lösung suche.
- Neuste Tipps
- Aufgaben und Lösungen
- Einbinden von Includes
- Eigene Dateiendung für Includes
- Inhaltsverzeichnis erzeugen
- Normalisierte (kanonische) Referenzen – "index.php" und ".php" in siteinternen Links entfernen
title-Element mit dem Inhalt der erstenh1-Überschrift füllen- URL der aktuellen Seite ausgeben
- Gittermaß für flüssige Thumbnailübersicht für Galerien
- Gesuchte Skripte
- Stilregel hinzufügen – abhängig vom längsten Inhalt eines Elementes (Anliegen)
- Inhalt eines spezifischen Elementes auslesen (Anliegen)
- Link-Elemente: rel="prev"/ rel="next"(Anliegen)
- Für den Druck: Linkziele (Anliegen)
- Syntaxhighlighting von HTML-, CSS- und PHP-Beispielcode (Anliegen)
- Wechselnde Hintergrundfarbe für gerade und ungerade Tabellenzeilen (Anliegen)
- Weiterführende Links
Neuste Tipps
- 04.04.2009
- 17.05.2008
- Prüfung der Verfügbarkeit aller Links
- 21.02.2007
- 21.10.2006
- Stilregel hinzufügen – abhängig vom längsten Inhalt eines Elementes (Anliegen)
- Sitespezifische Navigation (Anliegen)
- Neues Merkmal in auto-toc:
id-Attribute für jeden Listenpunkt - Wechselnde Hintergrundfarbe für gerade und ungerade Tabellenzeilen (Anliegen)
- 11.12.2005
- 15.11.2005
- 11.11.2004
- 16.07.2004
- Start der Seite
Aufgaben und Lösungen
Einbinden von Includes
Aufgabe
In der Kürze liegt die Würze.
Dir ist
<?php include "meta.inc" ?>
lieber als
<?php include "/www/domain.de/meine-includes/meta.inc"
?>
Was ist nötig um auf die fett hervorgehobenen Pfadteile zu verzichten?
Lösung
- Bestimmen Sie zunächst zweifelsfrei den korrekten Pfad zu den Includes.
- Legen Sie eine Datei
test.phpim gleichen Verzeichnis wie Ihre Includes an und laden Sie sie hoch.
http://domain.de/meine-includes/test.php:<?php if (isset($_GET['path']) ) { header ("Content-Type: text/html;charset=utf-8"); $width = strlen($_SERVER['SCRIPT_FILENAME']); echo <<<EOD <p>Benutze diesen Pfad, um das aktuelle Script einzubinden:<br> <input type="text" size="${width}" onFocus="this.select()" value="${_SERVER['SCRIPT_FILENAME']}"> EOD; } ?> - Rufen Sie die Datei im Browser auf und hängen Sie ein
?pathan die URL:
http://domain.de/meine-includes/test.php?path - Der korrekte Pfad zum Einbinden wird Ihnen in einem Dialogfeld
angezeigt. Nehmen wir an, die Anzeige lautet:
/www/domain.de/htdocs/meine-includes/test.php
Kopieren Sie den Pfad (fett hervorgehobener Teil). Achtung: abschließenden Schrägstrich nicht vergessen.
- Legen Sie eine Datei
- Geben Sie den Pfad zu Ihren Includes einmalig am Anfang Ihrer Dokumente
an.
- Legen Sie dafür eine Datei
/meine-includes/header.incin Ihrer Sitean:<?php set_include_path(get_include_path() . PATH_SEPARATOR . "/www/domain.de/htdocs/meine-includes/"); ?>
Der fett hinterlegte Teil ist der Teil, den Sie eben kopiert haben. - Fügen Sie dieses erstes Include ganz an den Anfang aller Ihrer
Dokumente ein. Da der Pfad zu diesem Zeitpunkt noch nicht bekannt
ist, muss dafür noch der lange Pfad verwendet werden.
dokument-eins.php:
<?php include "/www/domain.de/meine-includes/header.inc" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="de" xmlns="http://www.w3.org/1999/xhtml" xml:lang="de"> <head> . . .
- Legen Sie dafür eine Datei
- Für alle weiteren Includes können Sie jetzt die Kurzschreibweise
verwenden:
<?php include "/www/domain.de/meine-includes/header.inc" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang="de" xmlns="http://www.w3.org/1999/xhtml" xml:lang="de"> <head> <?php include "meta.inc" ?> . . .
Eigene Dateiendung für Includes
Aufgabe
Includes sollen sich leicht von anderen PHP-Skripten unterscheiden
lassen: anhand der Dateiendung .inc
Das Einbinden eines Includes sähe dann so aus:
<?php include "meta.inc" ?>
Solche Textdateien kann einer Fremder durch Raten und Aufrufen eines passenden URLs im Browser einsehen. Dies soll verhindert werden.
Lösung
Schließen Sie die Zugriffsmöglichkeit auf *.inc in der
Datei .htaccess aus. Tragen Sie dort folgenden Code an beliebiger
Position ein:
# Includes duerfen nicht per HTTP aufgerufen werden. <Files *.inc> order allow,deny deny from all </Files>
Inhaltsverzeichnis erzeugen
Aufgabe
Hier geht es um ein PHP-Skript, ich nenne es auto-toc,
welches ein kurzes und ein vollständiges Inhaltsverzeichnisses
für ein einzelnes HTML-Dokument erzeugt.
Es macht viel Mühe solche Inhaltsverzeichnisse mit dokument-internen
Links basierend auf den h-Elementen bei umfangreichen Dokumenten
zu erstellen – von der Fehlerträchtigkeit einmal ganz zu schweigen.
Merkmale
- XHTML
Das Skript erzeugt XHTML - Kurzes und langes Verzeichnis
Ein kurzes Inhaltsverzeichnis (class="quicktoc") und ein vollständiges Inhaltsverzeichnis (class="fulltoc") sind möglich.
Das kurze Inhaltsverzeichnis dient dem groben Überblick. Seine Links zeigen nicht auf Überschriften im Inhalt, sondern auf Listenpunkte im vollständigen Inhaltsverzeichnis.
Das vollständige Inhaltsverzeichnis dient dagegen dem Gesamtüberblick und enthält Links auf all die Überschriften, dessen Ebenen der Nutzer im Skript voreingestellt hat.
Der Nutzer hat auch die Möglichkeit nur jeweils eines der beiden Inhaltsverzeichnisse erzeugen zu lassen.
Klingt kompliziert? Leichter verständlich wird das Ganze an der Beispielseite.
Die Voreinstellungen stehen im Kopf des Skriptes. - Verschachtelung
Das Inhaltsverzeichnis besteht aus verschachteltenul. - Startebene
Es kann eingestellt werden, ab welcher Überschriftenebene Links erzeugt werden.
Im Beispiel wird auf die Überschrifth1undh2nicht verwiesen:h1trägt den Sitenamen,h2den Seitennamen.
Die Voreinstellung steht im Kopf des Skriptes. idals Zielanker
Als Zielanker werdenid-Attribute genutzt. Besitzt eine Überschrift keineidwird eineidnach einem Buchstabe-Zahl-Muster erzeugt.- Vorhandene Attribute
Vorhandene Attribute werden nicht angetastet - Vorhandene Inline-Elemente
Vorhandene Inline-Elemente imh-Element werden nicht angetastet - Elternelement DIV
Sollten Überschriften von einem oder mehrerenDIVseingeschlossen sein, stört dies die Erzeugung des AutoTOC nicht. - Zeilenumbrüche
in der Überschrift stören die Erzeugung des Inhaltsverzeichnisses nicht. idfür jeden Listenpunkt im Inhaltsverzeichnis
Dies erlaubt das gezielte Ausblenden einzelner Einträge.
Interessant kann diese Option zum Beispiel sein, wenn man für Screenreadernutzer Überschriften auch für Bereiche wie Kopf, Navigation, Fuß oder Nachrichten verwendet, diese jedoch für das Medium Bildschirm per CSS ausblenden möchte.
Sehenden erschließen sich diese Bereich intuitiv allein anhand der Gestaltung.
#fulltoc-h-2-2 { display: none; }würde den Eintrag "Geheimrat Dr. Oldenburg" im Beispieldokument ausblenden.
Lösung
Ich danke Stefan Fröhlich, der das Skript auf meine Anregung hin verfasst hat.
Dokument vor dem Parsen:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="de" xml:lang="de" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Pomologie | Gärtner Hans Eden</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
<h1>Gärtner Hans Eden</h1>
<h2>Pomologie</h2>
<p>Hier geht es um Apfelkunde.</p>
<?php include "autotoc.inc" ?>
<h3 id="bekannte-sorten">Bekannte Sorten</h3>
<h4 id="boskoop">Boskoop</h4>
<p>Der <em>Schöne von Boskoop</em> ist als Zufallssämling 1856 in Boskoop,
Niederlande, entdeckt worden.</p>
<h5>Züchter</h5>
<p>Rob van de Booskopp</p>
<h4 class="herkunft-usa">Golden Delicious</h4>
<p>Es handelt sich um eine sehr pflegeintensive Sorte.</p>
<h3>Wenig bekannte Sorten</h3>
<h4>Berlepsch</h4>
<p>Der Berlepsch oder auch <em>Goldrenette Freiherr von Berlepsch</em> ist
eine Sorte des Kulturapfels (Malus domestica).</p>
<h4>Geheimrat Dr. Oldenburg</h4>
<p><em>Geheimrat Oldenburg</em> ist eine Apfelsorte, die 1897 an der damaligen
Höheren Lehranstalt für Obstbau zu Geisenheim gezüchtet wurde.</p>
</body>
</html>
Dokument nach dem Parsen:
Quelltext des Skriptes auto-toc.inc:
<?php
# Name: auto-toc
# Zweck: Erzeugen eines Inhaltsverzeichnisses für die jeweilige Seite
# Erstellungsjahr: 2004
# Zuletzt geaendert: November 2006
# Autor: Stefan Froehlich <Stefan@Froehlich.Priv.at>
# Idee: Andreas Borutta <http://borumat.de/kontakt>
function toc($string) {
# Globale Konfigurationsparameter pruefen und ggf. mit Standardwerten belegen
if (is_null($GLOBALS['show_quicktoc'])) $GLOBALS['show_quicktoc'] = true;
if (is_null($GLOBALS['show_fulltoc'])) $GLOBALS['show_fulltoc'] = true;
if (is_null($GLOBALS['toc_toplevel'])) $GLOBALS['toc_toplevel'] = 3; # ab h3
if (is_null($GLOBALS['toc_fulldepth'])) $GLOBALS['toc_fulldepth'] = 2; # 2 Ebenen, also hier h3 und h4
# Alle Ueberschriften der gesuchten Ebenen einfangen
preg_match_all(sprintf('#<h([%1$d-%2$d])\s*([^>]+)?>(.*?)</h[%1$d-%2$d]>#is', $GLOBALS['toc_toplevel'], $GLOBALS['toc_toplevel']+$GLOBALS['toc_fulldepth']-1), $string, $matches, PREG_OFFSET_CAPTURE);
$offset = 0;
if ($GLOBALS['show_quicktoc']) {
# Ueberschrift fuer das kurze Verzeichnis
# "\n" fuegt einen Zeilenumbruch ein
$output .= '<div class="quicktoc">Kurzes Inhaltsverzeichnis:' . "\n";
$output .= '<ul>' . "\n";
}
$level = array();
foreach ($matches[1] as $key => $value) {
# Fuer jede Ueberschrift Name und Level extrahieren
$temp['name'] = $matches[3][$key][0];
$temp['level'] = $matches[1][$key][0]-$GLOBALS['toc_toplevel'];
# Zaehler fuer die aktuelle Ebene erhoehen, fuer alle
# darunterliegenden Ebenen zuruecksetzen
$level[$temp['level']]++;
for ($i=$temp['level']+1; $i<=$GLOBALS['toc_fulldepth']; $i++) $level[$i] = 0;
# Hat das Tag eine zugewiesene Klasse, so wird diese uebernommen
if (($matches[2][$key][1] > 0) && preg_match('#id="([^"]+)"#', $matches[2][$key][0], $tags)) $tag = $tags[1];
else {
# Ist keine Klasse vorhanden, muss eine eindeutige Kennung erzeugt werden
$tag = 'h';
for ($i=0; $i<=$temp['level']; $i++) $tag .= '-' . $level[$i];
$temp['id'] = $tag;
$string = substr_replace($string, sprintf(' id="%s"', $tag), $matches[1][$key][1]+1+$offset, 0);
$offset += strlen($tag)+6;
}
$temp['id'] = $tag;
# Eintrag fuer das lange Verzeichnis abspeichern
$toc[] = $temp;
if ($GLOBALS['show_quicktoc'] && ($temp['level'] == 0)) {
# Wird ein kurzes Verzeichnis gewuenscht, koennen die
# Ueberschriften der obersten Ebene gleich ausgegeben werden
$output .= " <li id=\"quicktoc-" . $temp['id'] . "\"><a href=\"#";
if ($GLOBALS['show_fulltoc']) {
$output .= "fulltoc-";
}
$output .= $temp['id'];
$output .= '">' . $temp['name'] . '</a></li>' . "\n";
}
}
# Kurzes Verzeichnis abschliessen
if ($GLOBALS['show_quicktoc']) $output .= "</ul>\n</div>\n";
# Langes Verzeichnis ausgeben
if ($GLOBALS['show_fulltoc']) {
$output .= '<div class="fulltoc">Vollständiges Inhaltsverzeichnis:' . "\n";
$output .= '<ul>' . "\n";
$level = 0;
$first = true;
foreach ($toc as $line) {
while ($line['level'] > $level) {
$output .= str_repeat(' ', $level+1) . '<ul>' . "\n";
$level++;
$first = true;
}
while ($line['level'] < $level) {
$output .= ' ' . str_repeat(' ', $level) . '</li>' . "\n";
$output .= str_repeat(' ', $level) . '</ul>' . "\n";
$level–;
}
if ($first) $first = false;
else $output .= ' ' . str_repeat(' ', $level) . '</li>' . "\n";
$output .= ' ' . str_repeat(' ', $level) . '<li';
$output .= ' id="fulltoc-' . $line['id'] . '"';
$output .= '><a href="#' . $line['id'] . '">' . $line['name'] . '</a>' . "\n";
}
while (0 < $level) {
$output .= ' ' . str_repeat(' ', $level) . '</li>' . "\n";
$output .= str_repeat(' ', $level) . '</ul>' . "\n";
$level–;
}
$output .= ' ' . str_repeat(' ', $level) . '</li>' . "\n";
$output .= '</ul>' . "\n";
$output .= '</div>' . "\n";
}
$output .= $string;
return $output;
}
ob_start('toc');
?>
Normalisierte (kanonische) Referenzen – "index.php" und ".php" in siteinternen Links entfernen
Aufgabe
Manche HTML-Editoren (Beispiel Dreamweaver) können keine kanonischen Links erzeugen. Wenn der Autor sie händisch erzeugt, versagt ihr Sitemanagement.
Daher soll die Kanonizität beim Ausliefern gewährleistet werden.
| Vorher | Nacher |
|---|---|
| Normale Dateien | |
<href="/foo.php"> |
<href="/foo"> |
<href="/bar/foo.php"> |
<href="/bar/foo"> |
| Directory Index | |
<href="/index.php"> |
<href="/"> |
<href="/bar/index.php"> |
<href="/bar/"> |
Das Skript soll mit diversen Sonderfällen klarkommen:
| Sonderfall | Kommentar |
|---|---|
<a href="/bar/foo.php#zot"> |
Fragmentidentifikator |
<href = "/bar/foo.php"> |
Leerzeichen vor und nach dem Gleichheitszeichen |
<a href="/bar/foo.php" class="lorem"> |
Mit Attribut nach href |
<a class="ipsum" href="/bar/foo.php"> |
Mit Attribut vor href |
<a href="/bar/foo.php?a=zot"> |
Mit Query-Part |
<a href = "/bar/foo.php"> |
Mit Leerzeichen vor und nach dem Gleichheitszeichen hinter dem Attribut href |
<form action="/bar/foo.php" method="get"> |
Referenz steht im Attribut action im Element form |
<a Href="/bar/foo.php"> |
Majuskel im Attribut href |
<A href="/bar/foo.php"> |
Majuskel im Element |
<a href="./foo.php"> |
dokument-relative Referenzierung |
<a href="/bar/foo.htm"> |
Endung .htm |
<a href="/bar/foo.html"> |
Endung .html |
Lösung
Ich danke Carsten Wiedmann und Michael Fesser, die dieses Skript auf meine Anregung hin verfasst haben.
Einbinden des Skriptes canonical-references.inc:
Fügen Sie das Include irgendwo im Kopf ihrer Datei an
. . . <?php include "canonical-references.inc"; ?> </head> . . .
Quelltext des Skriptes canonical-references.inc:
<?php
# Name: canonical-references
# Zweck: Umwandlung von nicht-kanonischen siteinternen Referenzen in kanonische
# Autoren: Carsten Wiedmann <info@wiedmann-online.de> und Michael Fesser <netizen@gmx.de>
# Ergaenzungen von: Stefan Froehlich <Stefan@Froehlich.Priv.at>
# Idee: Andreas Borutta <http://borumat.de/kontakt>
# Erstellungsjahr: Februar 2007
function callback($buffer) {
$pattern = '%
( # Beginn Subpattern $1
< # Beginn Tag
(?:a|form)\s # Elementname
[^>]* # beliebige Attribute
(?:href|action)\s*=\s* # Zielattribut
["\'] # Attributbegrenzer
(?<!http|https).*? # Beginn Attributwert, nur interne URIs
) # Ende Subpattern $1
(?:index)? # optionaler Default-Name
\.(?:php|[psx]?html?) # Dateiendung
( # Beginn Subpattern $2
(?:[\?#][^>]*)? # optionaler Query-String und/oder FI
["\'] # Attributbegrenzer
[^>]* # beliebige weitere Attribute
> # Ende Tag
) # Ende Subpattern $2
%ix';
return preg_replace($pattern, '$1$2', $buffer);
}
ob_start('callback');
?>
- Testdokument ohne das Skript
- Das gleiche Testdokument mit eingebundenem Skript
Zur Gewährleistung von kanonischen
Links bei der Rückgabe durch den Server existiert ein fertiger
Anweisungsblock für die Steuerdatei .htaccess. Vielleicht
ist dies ebenfalls interessant für Sie?
title-Element mit dem Inhalt der ersten h1-Überschrift
füllen
Aufgabe
Meist ist die erste h1-Überschrift auch ein vernünftiger title.
Das Skript auto-title füllt das title-Element
mit dem Inhalt der ersten h1. Besonders nach Änderungen
am h1 wird leicht das dan ebenfalls nötige Ändern des title vergessen.
Details der Funktionsweise stehen im Kopf des Skriptes.
Lösung
Ich danke Stefan Fröhlich für die Erstellung des Skriptes auf meine Anregung hin.
Einbinden des Skriptes auto-title.inc:
. . . <title> <?php include "auto-title.inc" ?> </title> . . .
Quelltext des Skriptes auto-title.inc:
<?php
# Name: auto-title
# Zweck: title-Element mit dem Inhalt des ersten H1 fuellen
# Erstellungsjahr: 2004
# Autor: Stefan Froehlich <Stefan@Froehlich.Priv.at>
# Idee: Andreas Borutta <http://borumat.de/kontakt>
# Liest den Inhalt des ersten H1 aus
# Entfernt im Ausgelesenen alle weiteren Tags (z.B. die
# Tags von Inline-Elementen oder BRs), entfernt kein Linefeed
# Geben Siet Inhalt aus
# Wenn statt des ersten H1 das erste H2 ausgelesen werden soll,
# ersetze in Zeile 2 "h1" im Starttag und im Endtag
$handle = fopen($_SERVER["SCRIPT_FILENAME"],"r");
preg_match("#<h1>([^(].*)</h1>#isU",fread($handle,filesize($_SERVER["SCRIPT_FILENAME"])),$match);
echo preg_replace("#<[^>]+>#","",preg_replace("#<br\s*/?>#i"," ",$match[1]));
?>
| deine-domain.de
URL der aktuellen Seite ausgeben
Aufgabe
Ausgeben der URL der aktuellen Seite. Dies ist z.B. für den Ausdruck nützlich.
Lösung
Ich danke Adam Schmalhofer, der das Skript auf meine Anregung hin verfasst hat.
url.inc:
<?php
# Gibt den URL der aktuellen Seite aus.
$url = $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
printf('<p class="url">URL dieser Seite: http://%s</p>', $url);
?>
foo.php vor dem Parsen:
. . . <?php include "url.inc" ?> . . .
Für das Beispiel befinden wir uns auf http://example.tld/foo/
foo.php nach dem Parsen:
. . .
<p class="url">URL dieser Seite: http://exammple.tld/foo/</p>
. . .
Gittermaß für flüssige Thumbnailübersicht für Galerien
Aufgabe
Um für Thumbnailübersichten für Bildergalerien eine flüssige Anordnung
zu realisieren, bieten sich div an.
Damit alle Boxen in einem gleichmäßigen Raster angeordnet sind, müssen
sie ein festes Maß erhalten. Dafür muss der Autor die größte aller Bildhöhen
und -breiten ermitteln. Diese mühsame Aufgabe soll das Skript grid-size.inc erledigen.
Details zur Funktionsweise stehen im Kopf des Skriptes.
Lösung
Ich danke Michael Praast für die Erstellung des Skriptes auf meine Anregung hin.
Einbinden des Skriptes grid-size.inc:
. . . <?php include "grid-size.inc" ?> </head> . . .
Quelltext des Skriptes grid-size.inc:
<?php
# Name: grid-size
# Zweck: Gittermass fuer Bildergalerieuebersichten ausgeben
# Erstellungsjahr: 14.11.2005
# Autor: Michael Praast <http://www.praast.de/>
# Idee: Andreas Borutta <http://borumat.de/kontakt>
# Beschreibung:
# Das Skript dient der Gestaltung von Thumbnailseiten fuer Bildergalerien
# in einer "fluessigen" Anordnung, also einer Gestaltung, die sich der Fensterbreite anpasst.
# Dafuer ist ein Rastermass in festen Breiten anzugeben. Das Skript ermittelt
# die Rastermasse automatisch aus den Bildgroessen. Es gibt das Mass als
# interne Stilregel aus.
# Beispiel:
# <style type="text/css">
# div.galeriethumbs div{ width: 210px; height: 210px;}
# </style>
# Das Skript wird als Include eingebunden.
# Die Stilregel wird an der Stelle ausgegeben, wo sich das Include befindet.
# Der Autor kann beliebige Struktur in seinem HTML-Code nutzen.
# Vorraussetzungen:
# Die Bildgroessen muessen in den Attributen width und height angegeben sein.
# Die Seite sollte keine weiteren Bilder enthalten als die Thumbnails, wenn diese groesser
# sind als die Thumbnails, denn das Skript liest alle Bilder aus und zieht deren Groessen
# zur Ermittlung des Rastermasses heran.
# Optionen:
# Es gibt drei Variablen zum Steuern der Wirkungsweise des Skriptes:
#
# 1 Extra-Weite und -Hoehe in px um die maximalen Kantenlaengen der Bilder herum
# Beispiel: $extrawidthheight = "30";
#
# 2 Seitenverhaeltnisse des Rasters
# true: Rastermass ist zwingend quadratisch
# false: Seitenverhaeltnis des Rasters ergibt sich aus den Bildmassen
# Beispiel: $square = true;
#
# 3 CSS-Selector der im interen Stylesheet angewendet wird
# Dieser muss je nach verwendeter HTML-Struktur angepasst werden.
# Beispiel: $selector = "div.galeriethumbs div";
# fuer eine Struktur wie:
# <div class="galeriethumbs">
# <div><a . . .><img . . . /></a></div>
# <div><a . . .><img . . . /></a></div>
# . . .
# </div>
#
# Beispiel: $selector = "div.galeriethumbs table";
# fuer eine Struktur wie:
# <div class="galeriethumbs">
# <table><tr><td><a . . .><img . . . /></a></td></tr></table>
# <table><tr><td><a . . .><img . . . /></a></td></tr></table>
# . . .
# </div>
$extrawidthheight = "30";
$square = true;
$selector = "div.galeriethumbs div, div.galeriethumbs table";
##########Don't touch!#########
// von welcher Datei werde ich aufgerufen?
$vonwo = $_SERVER['SCRIPT_FILENAME'];
// aufrufende Datei einlesen
$datei = file_get_contents($vonwo);
$start = "<img";
$ende = "/>";
// Filtere die IMGs heraus, Ablage in Array $printing
preg_match_all ( '#'.$start.'.*'.$ende.'#', $datei, $printing);
$anzahl = count($printing[0]);
$i = 0;
$Hmax=0;
$Bmax=0;
while ($i < $anzahl)
{
// Arrayfeld -> String
$temp = $printing[0][$i];
// Werte suchen
preg_match('/height=".*"/siU',$temp,$hoehe);
preg_match('/width=".*"/siU',$temp,$weite);
// Arraywert -> String
$hoehe = $hoehe[0];
$weite = $weite[0];
// extrahieren der Pixelangaben
$weite = eregi_replace( 'width="', "", $weite);
$weite = eregi_replace( '"', "", $weite);
$hoehe = eregi_replace( 'height="', "", $hoehe);
$hoehe = eregi_replace( '"', "", $hoehe);
// sind die aktuellen Werte groeszer als die bisherigen?
if ($hoehe > $Hmax) {$Hmax = $hoehe;}
if ($weite > $Bmax) {$Bmax = $weite;}
$i++;
}
// CSS setzen
$style ="<style type=\"text/css\">\n";
if ($square == true)
{
// quadratische Version gewuenscht
if ($Bmax < $Hmax)
{
$HBmax = $Hmax;
}
else
{
$HBmax = $Bmax;
}
$HBmax = $HBmax+$extrawidthheight;
$style .= "$selector{ width: ".$HBmax."px; height: ".$HBmax."px;".$raster_css."}\n";
}
else
{
// nicht quadratisch
$Bmax= $Bmax+$extrawidthheight;
$Hmax= $Hmax+$extrawidthheight;
$style .= "$selector{ width: ".$Bmax."px; height: ".$Hmax."px;".$raster_css."}\n";
}
$style.="</style>\n";
// CSS-Ausgabe
echo $style;
?>
Gesuchte Skripte
Hier beschreibe ich Aufgaben, für die ich ein Skript suche.
Site-Navigation (Anliegen)
Warum "Site-Navigation" und nicht "Navigation"? Um die Site-Navigation abzugrenzen von dem Inhaltsverzeichnis für eine einzelne Seite.
Ziel
Die Datei sitemap-data.php enthält alle nötigen Verweise
zur Erzeugung der Sitemap (als Dokument) und des Navigationsbereiches
auf jeder anderen Seite. Sie kann einen oder mehrere Navigationsbereiche
enthalten. Zum Beispiel:
- Service-Navigation
<ul id="service-nav-liste"> - Haupt-Navigation
<ul id="haupt-nav-liste">
Dem Bereich Service-Navigation werden Links zugeordnet, die auf jeder beliebigen Site enthalten sein sollten: Startseite, Sitemap, Kontakt
Die sitemap-data.php pflegt der Autor manuell.
Das Skript zeigt aus der Gesamtmenge der beiden Navigationsbereiche auf jeder Seite eine Teilmenge. Am Beispiel wird das Ziel klarer:
/sitemap-data.php
/incidunt/magna.php vor dem Parsen
<body> <h1>Magna</h1> . . . <?php $list_id = "service-nav-liste"; include "nav.inc"; ?> . . . <?php $list_id = "haupt-nav-liste"; include "nav.inc"; ?> . . . </body>
/incidunt/magna.php nach dem Parsen
Details
- Als erstes muss das Skript selbst seinen Aufenthaltsort feststellen: die Datei in der es sich befindet
- Ausgelesen werden soll vom Skript der gesamte Inhalt der
ULsmitid="service-nav-liste"undid="haupt-nav-liste"der Dateisitemap.php. - es dürfen vorkommen
- Zeichen in UTF-8
- beliebig viele
ul - Class-Attribute in den
ul - Attribute in
a,li,… - Kurz- oder Langschreibweise von relativen Referenzierungen:
/index.phpoder "/"
Wichtig: Im Zieldokument löscht das Skriptindex.phpstets heraus. - Absolute Referenzierungen (auf den dazugehörigen externen Seiten ist natürlich das Skript nicht eingebunden)
- Kommentare
- im Linktext darf vorkommen
- Markup wie
code - Umbrüche
- Entities
- Markup wie
amuss sich nicht das ganzelierstrecken- Es wird nur dann ein Ast einer untergeordneten Ebene angezeigt, wenn eine Seite aus diesem Ast aufgerufen wurde.
- Falls tiefere Ebenen unter dem aktuellen Listenpunkt existieren, wird die erste Ebene davon eingeblendet. Sonst wäre diese Ebene nicht erreichbar.
- Derjenige Listenpunkt in einer Navigationsleiste, der zur gerade
aktiven Seite gehört, darf kein Verweis mehr sein (er darf kein A-Element
besitzen): weil es den Nutzer irreleitet. Verweise sollten auf neue
Seiten verweisen und nicht auf dieselbe.
Dieser Listenpunkt wird mitstrongausgezeichnet. Seine Eltern- und Großelternelemente in der Navigationsliste werden mitemausgezeichnet. So ist sowohl der "Pfad" zum aktuellen Punkt als auch der Punkt selbst mit passendem Markup versehen.
Stilregel hinzufügen – abhängig vom längsten Inhalt eines Elementes (Anliegen)
Ziel
Die Navigationsleiste nimmt stets genau diejenige Breite in der Einheit ex ein,
dass der längste Listenpunkt aus der (verschachtelten) Navigation nicht
umbrochen wird.
Wenn der Autor neue Listenpunkte hinzufügt oder entfernt oder er die Verschachtelung ändert, muss er nichts manuell an der Stilregel für die Navigationsleiste ändern.
Das Skript, nennen wir es nav-auto-width, errechnet automatisch
den passenden Wert für die Breite und fügt ihn dynamisch als internes
Stylesheet im Kopf der Seite hinzu.
Am Beispiel wird es klarer:
nav.inc
<?php include="nav-auto-width.inc"; $padding = 1ex; $supplement = 2ex; ?> <ul class="nav"> <li><a . . .>Lorem ipsum</a></li> <li><a . . .>Veniam <ul> <li><a . . .>Dolor</a></li> <li><a . . .>Consectetu sitr</a></li> </ul> </li> <li><a . . .>Nostrud</a></li> </ul>
screen.css
. . .
.nav ul{ padding: 0; margin: 0; }
.nav li{ list-style-type: none; padding: 0; margin: 0; }
.nav li li, .nav li li li{ padding-left: 1ex; }
. . .
dolor.php vor dem Parsen
. . . <link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen" /> <link rel="stylesheet" href="/css/print.css" type="text/css" media="print" /> </head> <body> <h1>Dolor</h1> <?php include "nav.inc" ?> . . .
dolor.php nach dem Parsen
. . .
<link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen" />
<link rel="stylesheet" href="/css/print.css" type="text/css" media="print" />
<style type="text/css" media="screen"> .nav{ width: 18ex; } </style>
</head>
<body>
<h1>Dolor</h1>
<ul class="nav">
<li><a . . .>Lorem ipsum</a></li>
<li><a . . .>Veniam
<ul>
<li><strong>Dolor</strong></li>
<li><a . . .>Consectetur sit</a></li>
</ul>
</li>
<li><a . . .>Nostrud</a></li>
</ul>
. . .
Was muss der Autor erledigen?
- Er gibt im Skript einen Sicherheitszuschlag an. Falls z.B. einige Listenpunkte ein fettes Schriftgewicht bekommen, ist eine Erhöhung des Zuschlags sinnvoll
- Er gibt im Skript die Einrücktiefe an
Was muss das Skript erledigen?
- die Zeichenzahl und dessen Verschachtelungstiefe jedes Inhaltes von
libzw. von einemainnerhalb einesliwird ermittelt und daraus ein Betrag berechnet - zu dem Betrag wird der Sicherheitszuschlag addiert
- der längste Wert wird ermittelt und ausgegeben
- Beispielrechnung:
- die Polsterung beträgt
1ex - der Zuschlag beträgt
2ex - der längste Inhalt eines
liausul class="nav"istConsectetur sitund hat 15 Zeichen und befindet sich der Ebene 2 - Ergebnis für die Breite von
ul class="nav"ist:18ex
- die Polsterung beträgt
- Einfügen des Blocks
<style type="text/css" media="screen"> .nav{ width: 18ex; } </style>
in den Kopf der Seite
Inhalt eines spezifischen Elementes auslesen (Anliegen)
Es geht um eine kleine Variation des oben vorgestellten Skriptes zum
Füllen des Elementes title:
Es liest das erste h1 aus.
Nützlich wäre es, wenn man man ein per ID eindeutig benennbares Element
wählen könnte. Zum Beispiel <h2 id="content">…</h2>
Link-Elemente: rel="prev"/ rel="next"(Anliegen)
Manche Seiten stehen in einer bestimmten Reihenfolge, zum Beispiel
in Artikeln von Magazinen. Im Element link lässt sich diese
Reihenfolge angeben. Manche Benutzerprogramme können dann mit einer Funktion Nächstes bzw. Vorheriges zu
den Artikel navigieren.
Für das Beispiel nehmen wir folgende Reihenfolge von Artikeln an:
/08//08/familien-pino//08/saeuglingstransport//08/babybiker//08/familie-ohne-auto/
Der Artikel Babybiker sei geöffnet. Hinter dem /08/ liegt
der erste Artikel, das Editorial.
Vor dem Parsen
. . . <?php include "first-prev-next.inc" ?> </head> . . . <div class="nav"> <ol>
<li><a href="/08/">Editorial</a></li>
<li><a href="/08/familien-pino/">Familien-Pino</a></li>
<li><a href="/08/saeuglingstransport/">Säuglingstransport</a></li>
<li class="active>Babybiker</li>
<li><a href="/08/familie-ohne-auto/">Familie ohne Auto</a></li>
</ol> </div> . . .
Nach dem Parsen
. . .
<link rel="first" title="Editorial" href="/08/" />
<link rel="prev" title="Säuglingstransport" href="/08/saeuglingstransport/" />
<link rel="next" title="Familie ohne Auto" href="/08/familie-ohne-auto/" />
</head>
. . .
Für den Druck: Linkziele (Anliegen)
Beim Ausdruck geht das Linkziel verloren. Zwar kann man per CSS den URL als "generated content" ausgeben, aber das wird zum Einen nur von wenigen Browsern unterstützt und zum Anderen stören URLs direkt im Text die Lesbarkeit.
Besser ist ein Einfügen eines Verweiszeichens als fortlaufende Nummer und das Ausgeben einer Linkziel-Liste am Dokumentende.
Weitere Merkmale:
- Seiteninterne Links werden ebenfalls angegeben - als vollständiger URL. Dokument- bzw. root-relative Links werden also zu absoluten aufgelöst.
- Links, die mehrmals vorkommen, erhalten dieselbe Nummer
- Links können von der Behandlung durch das Skript ausgeschlossen
werden können. Dazu können innerhalb des PHP-Skriptes Selektoren
(ähnlich wie in CSS) angegeben werden.
- Beispiel 1: Navigation. Sie ist für den Druck ausgeblendet. Ihre Links sollen also weder den Zähler hochsetzen, noch sollen sie in der Linkziel-Liste auftauchen.
- Beispiel 2: Fußnotenverweiszeichen. Diese Links sollen zwar im Druck ausgegeben werden, aber nicht als Link "erkennbar" sein. Auch diese Links sollen weder den Zähler hochsetzen, noch sollen sie in der Linkziel-Liste erscheinen.
- Idealerweise greift das PHP-Skript auf den DOM zu.
"http://meine-domain.de/foo/" vor dem Parsen
. . .
<style type="text/css" media="screen">
span.linknummer, div.linkziele { position: absolute; left: -1000px; top: -1000px; width: 0; max-height: 0; overflow: hidden; display: inline; }
</style>
<style type="text/css" media="print">
/* Nicht als Link zeigen*/ a.fnz { text-decoration: none; color: black; }
/* Nicht zeigen*/ ul.navi { display: none; }
</style>
<?php include "linkziele.inc" ?>
</head>
. . .
<ul class="navi">
<li><a href="/seite-1/">Navi 1</a></li>
<li><a href="/seite-2/">Navi 2</a></li>
</ul>
. . .
<p>Lorem <a href="http://ipsum.de">ipsum</a> doloret.</p>
<p>Adipisit <a href="#sed">sed</a> consectutur.</p>
<p>Persitia <a href="../bar/vubir">vubir</a> olukat.</p>
<p>Ut enim <a class="fnz" href="#fn-1">[1]</a> minimim.</p>
<p>Laboris nisi<a class="fnz" href="#fn-2">[2]</a> ullamcor.</p>
<p>Sed do <a href="http://eiusmod.de/?a=b&c=d">eiusmod</a> tempor.</p>
<p>Kafitet <a href="#sed">sed</a> hesaltum.</p>
. . .
<div class="fussnoten">
<h4 id="fussnoten">Fußnoten</h4>
<ol>
<li id="fn-1">Enim quis iomur verdita.</li>
<li id="fn-2">Taride e fuzio mostamur.</li>
</ol>
</div>
"http://meine-domain.de/foo/" nach dem Parsen
. . . <ul class="navi">
<li><a href="/seite-1/">Navi 1</a></li>
<li><a href="/seite-2/">Navi 2</a></li>
</ul> . . . <p>Lorem <a href="http://ipsum.de">ipsum <span class="linknummer">{1}</span></a> doloret.</p>
<p>Adipisit <a href="#sed">sed <span class="linknummer">{2}</span></a> consectutur.</p>
<p>Persitia <a href="../bar/vubir">vubir <span class="linknummer">{3}</span></a> olukat.</p> <p>Ut enim <a class="fnz" href="#fn-1">[1]</a> minimim.</p>
<p>Laboris nisi<a class="fnz" href="#fn-2">[2]</a> ullamcor.</p>
<p>Sed do <a href="http://eiusmod.de/?a=b&c=d">eiusmod <span class="linknummer">{4}</span></a> tempor.</p> <p>Kafitet <a href="#sed">sed <span class="linknummer">{2}</span></a> hesaltum.</p> . . . <div class="fussnoten">
<h4 id="fussnoten">Fußnoten</h4>
<ol>
<li id="fn-1">Enim quis iomur verdita.</li>
<li id="fn-2">Taride e fuzio mostamur.</li>
</ol>
</div> . . . <div class="linkziele"> <h4 id="linkziele">Linkziele</h4> <ol> <li>http://ipsum.de</li> <li>http://meine-domain.de/foo/#sed</li> <li>http://meine-domain.de/bar/vubir</li> <li>http://eiusmod.de/?a=b&c=d</li> </ol> </div> </html>
Syntaxhighlighting von HTML-, CSS- und PHP-Beispielcode (Anliegen)
Für das Vorstellen von Beispielen von Quellcode wäre ein Skript hilfreich,
das die jeweiligen Start- und Endtags mit span-Containern
umhüllt, damit passende Selektoren gebildet werden können.
Vor dem Parsen
<pre> <h1>Lorem ipsum</h1> <p>Dolor sit <strong>amet </strong>, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut <a href="document.html">labore</a> et dolore magna aliqua.</p> </pre>
Nach dem Parsen
<pre> <span class="sh-bl"><h1></span>Lorem ipsum<span class="sh-bl"></h1></span> <span class="sh-bl"><p></span>Dolor sit <span class="sh-in"><strong></span>amet <span class="sh-in"></strong></span>, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut <span class="sh-a"><a href="document.html"></span>labore<span class="sh-a"></a></span> et dolore magna aliqua.<span class="sh-block"></p></span> </pre>
CSS
.sh-in{
color: green;
font-weight: bold;
}
.sh-bl{
color: blue;
font-weight: bold;
}
.sh-a{
color: #CC0099;
font-weight: bold;
}
Am Display ohne Highlighting-Skript
<h1>Lorem ipsum</h1> <p>Dolor sit <strong>amet </strong>, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut <a href="document.html">labore</a> et dolore magna aliqua.</p>
Am Display mit Highlighting-Skript
<h1>Lorem ipsum</h1> <p>Dolor sit <strong>amet </strong>, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut <a href="document.html">labore</a> et dolore magna aliqua.</p>
Wechselnde Hintergrundfarbe für gerade und ungerade Tabellenzeilen (Anliegen)
Ziel
Die Lesbarkeit von Datentabellen verbessert sich, wenn jede zweite Zeile einer Tabelle eine andere Hintergrundfarbe erhält.
Das Skript, nennen wir es alternating-row-classes.inc fügt
in table mit class="alt-row" den entsprechenden tr ein class="even" hinzu.
So kann der Autor über das zentrale Stylesheet die Hintergrundfarben
gestalten.
Am Beispiel wird dies klarer:
screen.css
. . .
td { background: . . .; }
.even td { background: . . .; }
th { background: . . .; }
.even th { background: . . .; }
. . .
dolor.php vor dem Parsen
. . . <?php include="alternating-row-classes.inc" ?> . . . <body> . . . <table class="foo alt-row"> <tr> <th>Lorem</th><td>Ipsum</td> </tr> <tr class="bar"> <th>Dolor</th><td>Sit</td> </tr> <tr> <th>Amet</th><td>Consectetur</td> </tr> <tr> <th>Adipisicing</th><td>Elit</td> </tr> </table> <table class="alt-row zot"> <tr> <th>Lorem</th><th>Ipsum</th> </tr> <tr> <td>Dolor</td><td>Sit</td> </tr> <tr> <td>Amet</td><td>Consectetur</td> </tr> <tr> <td>Adipisicing</td><td>Elit</td> </tr> </table> <table class="alt-row"> <tr> <th></th><th>Ipsum</th><th>Sed</th> </tr> <tr> <th>Dolor</th><td>Sit</td><td>Do</td> </tr> <tr> <th>Amet</th><td>Consectetur</td><td>Eiusmod</td> </tr> <tr> <th>Adipisicing</th><td>Elit</td><td>Tempor</td> </tr> </table> . . . </body> </html>
dolor.php nach dem Parsen
. . . <body> . . . <table class="foo alt-row"> <tr> <th>Lorem</th><td>Ipsum</td> </tr> <tr class="even bar"> <th>Dolor</th><td>Sit</td> </tr> <tr> <th>Amet</th><td>Consectetur</td> </tr> <tr class="even"> <th>Adipisicing</th><td>Elit</td> </tr> </table> <table class="alt-row zot"> <tr> <th>Lorem</th><th>Ipsum</th> </tr> <tr class="even"> <td>Dolor</td><td>Sit</td> </tr> <tr> <td>Amet</td><td>Consectetur</td> </tr> <tr class="even"> <td>Adipisicing</td><td>Elit</td> </tr> </table> <table class="alt-row"> <tr> <th></th><th>Ipsum</th><th>Sed</th> </tr> <tr class="even"> <th>Dolor</th><td>Sit</td><td>Do</td> </tr> <tr> <th>Amet</th><td>Consectetur</td><td>Eiusmod</td> </tr> <tr class="even"> <th>Adipisicing</th><td>Elit</td><td>Tempor</td> </tr> </table> . . . </body> </html>
Details
- Das Skript kann die zu behandelnden Tabellen auch erkennen, wenn
das
class-Attribut nicht nur den Wertalt-rowenthält:
<table class="foo alt-row">
<table class="alt-row zot"> - Das Skript respektiert bereits vorhandene Werte in
trund fügt den Wertevenhinzu:
<tr class="bar">
<tr class="even bar">
Ausblick
Für komplexere Tabellen, die mit thead, tbodyund tfoot ausgezeichnet
sind und wo die Attribute scope="row" oder scop="col" gesetzt sind, folgt
hier vielleicht später einmal eine Skizze. Aber schon einen Farbfächer
zu entwerfen, der derart viele Farben enthält und dennoch bei allen denkbaren
Paarungen aus Vorder- und Hintergrundfarbe hinreichenden Kontrast gewährleisten
kann, ist anspruchsvoll. Über Hinweise zu
Beispielseiten zu diesem Thema freue ich mich.