Sprunglink zum Inhalt Sprunglink zur Service-Navigation

Andreas Borutta

Service Navigation

Suche siteweit

Tipps und Skripte 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.

Ähnliche Themen, die Sie vielleicht ebenfalls interessieren:
Kurzes Inhaltsverzeichnis:
Vollständiges Inhaltsverzeichnis:

Neuste Tipps

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
  1. Bestimmen Sie zunächst zweifelsfrei den korrekten Pfad zu den Includes.
    • Legen Sie eine Datei test.php im 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 ?path an 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.
  2. Geben Sie den Pfad zu Ihren Includes einmalig am Anfang Ihrer Dokumente an.
    • Legen Sie dafür eine Datei /meine-includes/header.inc in Ihrer Site an:
      <?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>
      . . .
      
  3. 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
  1. XHTML
    Das Skript erzeugt XHTML
  2. 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.
  3. Verschachtelung
    Das Inhaltsverzeichnis besteht aus verschachtelten ul.
  4. Startebene
    Es kann eingestellt werden, ab welcher Überschriftenebene Links erzeugt werden.
    Im Beispiel wird auf die Überschrift h1 und h2 nicht verwiesen: h1 trägt den Sitenamen, h2 den Seitennamen.
    Die Voreinstellung steht im Kopf des Skriptes.
  5. id als Zielanker
    Als Zielanker werden id-Attribute genutzt. Besitzt eine Überschrift keine id wird eine id nach einem Buchstabe-Zahl-Muster erzeugt.
  6. Vorhandene Attribute
    Vorhandene Attribute werden nicht angetastet
  7. Vorhandene Inline-Elemente
    Vorhandene Inline-Elemente im h-Element werden nicht angetastet
  8. Elternelement DIV
    Sollten Überschriften von einem oder mehreren DIVs eingeschlossen sein, stört dies die Erzeugung des AutoTOC nicht.
  9. Zeilenumbrüche
    in der Überschrift stören die Erzeugung des Inhaltsverzeichnisses nicht.
  10. id fü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:

So sieht's aus

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');

?>

Alle Dateien eines Verzeichnisses als Linkliste

Aufgabe

Alle Dateinamen des aktiven Verzeichnisses werden extrahiert und als Zielanker in einer Linkliste verwendet.

Lösung

Ich danke Carsten Wiedmann für die Erstellung des Skriptes auf meine Anregung hin.

Einbinden des Skriptes directory-map.inc:

<body>
<h1>Directory Map</h1>
<?php include "directory-map.inc" ?>
</body>

Quelltext des Skriptes directory-map.inc:

<?php

             # Name: directory-map
            # Zweck: Erzeugen einer Linkliste aus den Dateinnamen des aktiven Verzeichnisses
  # Erstellungsjahr: 26.07.2004
            # Autor: Carsten Wiedmann <info@wiedmann-online.de>
             # Idee: Andreas Borutta <http://borumat.de/kontakt>

# extrahiert alle Dateinamen ab/des aktuellen Verzeichnisses und verwendet sie als Zielanker
# schreibt jeden Verweis in ein li-Element
# Beispiel:
# [css-vokabular.php]
# <html>. . .<h1>CSS Vokabular und Syntax</h1>
# Ergebnis:
# <ul>. . .<li><a href="css-vokabular">CSS Vokabular und Syntax</a></li>. . .</ul>

define('EXTENSION', 'php,html');
// '%ext%'  = Dateien mit welcher Endungen, mit Kommas getrennt, sollen aufgelistet werden
//            (z.B: define('EXTENSION', 'php,html'); )
// false    = alle Dateien werden aufgelistet

define('EXCL_DATEI', false);
// '%Name%' = Dateien, mit Kommas getrennt, die immer aufgelistet werden sollen
// false    = keine Ausnahmen

define('INCL_DATEI', false);
// '%Name%' = Dateien, mit Kommas getrennt, die nie aufgelistet werden sollen
// false    = keine Ausnahmen

define('SUBDIR', true);
// true     = Unterverzeichnisse werden mit aufgelistet
// false    = Unterverzeichnisse werden nicht mit aufgelistet

define('SCHREIBMULTIVIEW', true);
// true     = Links werden ohne Dateiendung geschrieben
// false    = Links werden mit Dateiendung geschrieben

define('UTF8BOM', true);
// true     = Prüfen ob die Datei wo der Linktext herkommt in UTF-8 kodiert ist.
//            Wenn nein, konvertiert es den Linktext für die Ausgabe nach UTF-8
//            Dies ist interessant, wenn es noch Dateien in z.B. ISO-8859-1 gibt
//            und Umlaute vorkommen.
// false    = schaltet diese Überprüfung aus

define('LINKSTIL', 'absolut');
// 'absolut'= Links werden ausgehend vom Root geschrieben
//            z.B.: <a href="/pfad/datei.php"></a>
// 'relativ'= Links werden ausgehend vom aktuelle Verzeichnis geschrieben
//            z.B.: <a href="datei.php"></a>

define('BASEURI', dirname($_SERVER['SCRIPT_NAME']));
// '%uri%/'  = hier ermittelt das Script die Start-URI für die Links

define('WORKDIR', dirname($_SERVER['SCRIPT_FILENAME']));
// '%Pfad%' = hier ermittelt das Script das Startverzeichnis
//            ab welchem es arbeiten

define('SCHREIBE_WORKDIR', false);
// true     = Das Startverzeichnis taucht als erster Listenpunkt auf
// false    = Das Startverzeichnis taucht nicht als erster Listenpunkt auf

function teste_utf8($teststring) {
    if ((chr(0xEF).chr(0xBB).chr(0xBF) == substr($teststring, 0, 3))) {
        return true;
    } else {
        for ($zeichen = 0; strlen($teststring) > $zeichen; $zeichen++) {

            if (0x80 > ord(substr($teststring, $zeichen, 1))) {
                $anz_oktett = 0;
            } elseif (0xC0 == (ord(substr($teststring, $zeichen, 1)) & 0xE0)) {
                $anz_oktett = 1;
            } elseif (0xE0 == (ord(substr($teststring, $zeichen, 1)) & 0xF0)) {
                $anz_oktett = 2;
            } elseif (0xF0 == (ord(substr($teststring, $zeichen, 1)) & 0xF0)) {
                $anz_oktett = 3;
            } else {
                return false;
            }

            for ($oktett = 0; $anz_oktett > $oktett; $oktett++) {
                if ((strlen($teststring) == ++$zeichen)
                || (0x80 != (ord(substr($teststring, $zeichen , 1)) & 0xC0))) {
                    return false;
                }
            }
        }
        return true;
    }
}

function lese_verzeichnisse($verzeichnis) {
    $excl_datei = array();
    $excl_datei = explode(',', EXCL_DATEI);

    $incl_datei = array();
    $incl_datei = explode(',', INCL_DATEI);

    if ((false !== is_dir($verzeichnis)) && ($dir = @opendir($verzeichnis))) {

        while (false !== ($datei = readdir($dir))) {
            if (SUBDIR && is_dir($verzeichnis.DIRECTORY_SEPARATOR.$datei)
            && ('.' != $datei) && ('..' != $datei)) {
                if ($datei = lese_verzeichnisse($verzeichnis.DIRECTORY_SEPARATOR.$datei)) {
                    $verzeichnisliste[] = $datei;
                }
            } elseif (!is_dir($datei) && !in_array($datei, $excl_datei)) {

                if (in_array($datei, $incl_datei)) {
                    $datei = $verzeichnis.DIRECTORY_SEPARATOR.$datei;
                } else {
                    $datei = $verzeichnis.DIRECTORY_SEPARATOR.$datei;
                    if (false !== EXTENSION) {

                        $pruef_datei = pathinfo($datei);
                        if (array_key_exists('extension', $pruef_datei)) {
                            $extension = explode(',', EXTENSION);
                        } else {
                            $pruef_datei['extension'] = '';
                        }

                        foreach ($extension as $ext) {
                            if ($pruef_datei['extension'] == trim($ext)) {
                                $ext = true;
                                break;
                            }
                        }
                        if (true !== $ext) {
                            continue;
                        }

                    }
                }
                $verzeichnisliste[] = $datei;
            } else {
                $verzeichnisliste[] = $verzeichnis;
            }

        }

    }
    closedir($dir);

    if (isset($verzeichnisliste)) {
        asort($verzeichnisliste);
        $verzeichnisliste = array_values($verzeichnisliste);
        return $verzeichnisliste;
    }
}

function hole_titel($datei) {
    if (false !== ($dateiinhalt = @file_get_contents($datei))) {

        $anfang = strpos(strtolower($dateiinhalt), '<'.'h1');
        $ende = strpos(strtolower($dateiinhalt), '</'.'h1'.'>', $anfang);
        $titel = strip_tags(substr($dateiinhalt, $anfang, $ende - $anfang));

        $titel = str_replace(array("\r", "\n", "\t"), ' ', $titel);
        $wort = strtok ($titel, ' ');
        $titel = '';
        while ($wort) {
            $titel .= ' '.$wort;
            $wort = strtok(' ');
        }
        $titel = trim($titel);

        if ((false !== $anfang) && (false !== $ende) && (false != $titel)) {
            return $titel;
        } else {
            return '&#60;'.basename($datei).'&#62; : kein Titel';
        }

    } else {
        return '&#60;'.basename($datei).'&#62; : Dateifehler';
    }
}

function schreibe_liste($verzeichnisliste = '', $durchlauf = 0) {
    flush();

    $baseuri = strtr(BASEURI, DIRECTORY_SEPARATOR, '/').'/';
    if ('//' == substr($baseuri, 0, 2)) {
        $baseuri = substr($baseuri, 1);
    }

    if (0 == $durchlauf) {
        $verzeichnisliste = lese_verzeichnisse(WORKDIR);

        echo "\n";
        if (SCHREIBE_WORKDIR) {
            if ('' == ($verzeichnis = substr($baseuri, 0, -1))) {
                $verzeichnis = '/';
            }
            echo '<ul>'."\n";
            echo str_repeat('    ', $durchlauf + 1).'<li>'.$verzeichnis."\n";
        }
    }

    if (is_array($verzeichnisliste)) {
        if (array_key_exists(2, $verzeichnisliste)) {
            echo str_repeat('    ', $durchlauf + 2).'<ul>'."\n";
        }

        foreach ($verzeichnisliste as $nr => $datei) {

            if (is_array($datei)) {

                $verzeichnis = reset($datei);
                if (!is_array($verzeichnis) && !is_dir($verzeichnis)) {
                    $verzeichnis = pathinfo($verzeichnis);
                    $verzeichnis = $verzeichnis['dirname'];
                }
                $verzeichnis = strtr($verzeichnis, DIRECTORY_SEPARATOR, '/');
                $verzeichnis = substr($verzeichnis, strlen(WORKDIR) + 1);

                if (false !== ($start = strrpos($verzeichnis, '/'))) {
                    $verzeichnis = substr($verzeichnis, $start + 1);
                }
                echo str_repeat('    ', $durchlauf + 3).'<li>'.$verzeichnis."\n";
                schreibe_liste($datei, $durchlauf + 2);
                echo str_repeat('    ', $durchlauf + 3).'</li>'."\n";

            } elseif (!is_dir($datei)) {

                $linktext = hole_titel($datei);
                if (UTF8BOM && !teste_utf8($linktext)) {
                    $linktext = utf8_encode($linktext);
                }

                $datei = pathinfo($datei);
                if (SCHREIBMULTIVIEW && array_key_exists('extension', $datei)) {
                    $datei = $datei['dirname'].DIRECTORY_SEPARATOR
                    .substr(basename($datei['basename'], $datei['extension']), 0 , -1);
                } else {
                    $datei = $datei['dirname'].DIRECTORY_SEPARATOR.$datei['basename'];
                }

                $datei = substr($datei, strlen(WORKDIR) + 1);
                $datei = strtr($datei, DIRECTORY_SEPARATOR, '/');
                if ('absolut' == LINKSTIL) {
                    $datei = rawurlencode($baseuri.$datei);
                } else {
                    $datei = rawurlencode($datei);
                }
                $datei = strtr($datei, array('%2F' => '/'));

                echo str_repeat('    ', $durchlauf + 3)
                .'<li><a href="'.$datei.'">'.$linktext.'</a></li>'."\n";
            }
        }

        if (array_key_exists(2, $verzeichnisliste)) {
            echo str_repeat('    ', $durchlauf + 2).'</ul>'."\n";
        }
    }

    if (0 == $durchlauf) {
        if (SCHREIBE_WORKDIR) {
            echo str_repeat('    ', $durchlauf + 1).'</li>'."\n";
            echo '</ul>'."\n";
        }
    }
}

schreibe_liste();
?>

Änderungsdatum einer Datei

Aufgabe

Ausgeben des Datums der letzten Speicherung der Datei.

Lösung

Einbinden des Skriptes lastmodified.inc:

. . .
<body>
<?php include "last-modified.inc" ?>
<h1>. . .</h1>
. . .

Quelltext des Skriptes lastmodified.inc:

<p class="aend">Zuletzt geändert am
<?php
$unixTime = filemtime($_SERVER["PATH_TRANSLATED"]);
if ($unixTime) {
 $speicherdatum = date("d.m.Y", $unixTime);
 $speicherzeit = date("H:i", $unixTime);
}
echo $speicherdatum;
?>
</p>

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');
?>

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?

Änderungsdatum der Zieldatei eines Links

Aufgabe

Eintragen des Datums der letzten Speicherung eines Linkzieles.

Lösung

Ich danke Thomas Scholz, der dieses Skript auf meine Anregung hin erstellt hat.

Einbinden des Skriptes lastmodified-href.inc:

. . .
<body>
<p><a href="/lorem/ipsum.php">Lorem</a> ipsum dolor sit amet, consectetur 
adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore 
magna aliqua.
<?php 
$href="/lorem/ipsum.php";
include "last-modified-href.inc";
?>
</p>
. . .

Quelltext des Skriptes lastmodified-href.inc:

<br /><span class="lastmod">Zuletzt geändert am:
<?php

             # Name: lastmodified-href
            # Zweck: Aenderungsdatum der Zieldatei eines Links ausgeben
  # Erstellungsjahr: 2004
            # Autor: Thomas Scholz <http://toscho.de/>
             # Idee: Andreas Borutta <http://borumat.de/kontakt>


# Fügt das Datum der letzten Änderung derjenigen Datei ein, 
# die in der Variable $href vor dem Include angegeben wird.
# Das Datum wird genau an der Position eingefügt, 
# wo sich das Include befindet.
# Beispiel für das Einbinden:
# <?php 
# $href="/lorem/ipsum.php";
# include "last-modified-href.inc";
# ?>

if ($href != rtrim($href, '/')) { // Für URLs, die auf '/' enden.
 $href .= 'index.php';
 }
$speicherdatumhref = filemtime(rtrim($_SERVER['DOCUMENT_ROOT'], '/')
. '/' . $href);
echo date("d.m.Y", $speicherdatumhref);
return;
?>
</span> 

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

So sieht's aus

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.

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:

  1. Service-Navigation <ul id="service-nav-liste">
  2. 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

So sieht's aus

/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

So sieht's aus

Details
  1. Als erstes muss das Skript selbst seinen Aufenthaltsort feststellen: die Datei in der es sich befindet
  2. Ausgelesen werden soll vom Skript der gesamte Inhalt der ULs mit id="service-nav-liste" und id="haupt-nav-liste" der Datei sitemap.php.
  3. es dürfen vorkommen
    1. Zeichen in UTF-8
    2. beliebig viele ul
    3. Class-Attribute in den ul
    4. Attribute in a, li
    5. Kurz- oder Langschreibweise von relativen Referenzierungen: /index.php oder "/"
      Wichtig: Im Zieldokument löscht das Skript index.php stets heraus.
    6. Absolute Referenzierungen (auf den dazugehörigen externen Seiten ist natürlich das Skript nicht eingebunden)
    7. Kommentare
  4. im Linktext darf vorkommen
    1. Markup wie code
    2. Umbrüche
    3. Entities
  5. a muss sich nicht das ganze li erstrecken
  6. Es wird nur dann ein Ast einer untergeordneten Ebene angezeigt, wenn eine Seite aus diesem Ast aufgerufen wurde.
  7. Falls tiefere Ebenen unter dem aktuellen Listenpunkt existieren, wird die erste Ebene davon eingeblendet. Sonst wäre diese Ebene nicht erreichbar.
  8. 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 mit strong ausgezeichnet. Seine Eltern- und Großelternelemente in der Navigationsliste werden mit em ausgezeichnet. 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?
Was muss das Skript erledigen?

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>

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:

  1. /08/
  2. /08/familien-pino/
  3. /08/saeuglingstransport/
  4. /08/babybiker/
  5. /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:

"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&amp;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&amp;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&amp;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>
&lt;h1&gt;Lorem ipsum&lt;/h1&gt;
&lt;p&gt;Dolor sit 
&lt;strong&gt;amet &lt;/strong&gt;,
consectetur adipisicing elit, sed do eiusmod	
tempor incididunt ut
&lt;a href=&quot;document.html&quot;&gt;labore&lt;/a&gt; 
et dolore magna aliqua.&lt;/p&gt;
</pre>
Nach dem Parsen
<pre>
<span class="sh-bl">&lt;h1&gt;</span>Lorem ipsum<span class="sh-bl">&lt;/h1&gt;</span>
<span class="sh-bl">&lt;p&gt;</span>Dolor sit 
<span class="sh-in">&lt;strong&gt;</span>amet <span class="sh-in">&lt;/strong&gt;</span>, 
consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut 
<span class="sh-a">&lt;a href="document.html"&gt;</span>labore<span class="sh-a">&lt;/a&gt;</span>
et dolore magna aliqua.<span class="sh-block">&lt;/p&gt;</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

Beispiel ansehen

. . .
<?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

Beispiel ansehen

. . .
<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
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.