Anzeige
Smartes Cloud Hosting für anspruchsvolle Projekte.
↬ Jetzt testen
Dr. Detlef Groth 2. August 2007

Bequemes Texten mit HTML und Javascript

Kein Beitragsbild

Beim Schreiben längerer Dokumente wünscht man sich häufig eine automatische Erstellung von Inhalts-, Literatur-, Abkürzungs- oder Stichwortverzeichnissen. Für Auszeichnungsprachen wie LaTex und bis zu einem gewissen Grad bei verschiedenen Text-Verarbeitungsprogrammen sind diese Fähigkeiten schon seit vielen Jahren Standard. Moderne JavaScript-Libraries bieten zwar eine ganze Menge an Möglichkeiten bei der Gestaltung von interaktiven Benutzerschnittstellen, aber beim alltäglichen Schreiben von Texten wird man leider nur unzureichend berücksichtigt. Wir zeigen Ihnen wie Verzeichnisse auf einfache Weise auch in HTML erstellt werden können.

Die verwendeten HTML-Tags
In unserem Fließtext verwenden wir HTML-Elemente für die logische Text-Auszeichnung, welche später in unsere Verzeichnisse aufgenommen werden sollen. Dazu zählen die folgenden Tags:

  • Acronym-Tags für ein Abkürzungsverzeichnis
  • Dfn-Tags für ein Definitionsverzeichnis
  • A-Tags mit Links zu externen Quellen für ein Linkverzeichnis
  • Header-Tags wie h1 oder h2 für das Inhaltsverzeichnis
  • Cite-tags für ein Literaturverzeichnis

Als Platzhalter werden Div-Tags mit einem Namen, die einen erkennbaren Bezug zu dem dazugehörigen logischen HTML-Element haben, gewählt. Sinnvolle Namen wären für Zitate JSDynListCite, für Abkürzungen JSDynListAcronym und für Definitionen JSDynListDfn. Außerdem werden für Inhaltsverzeichnisse JSDynListToc sowie für Linkververzeichnisse JSDynListLink verwandt. Der Prefix JS ist notwendig für die Einbettung in das hier bereits vorgestellte jsComponents-Framework. Diese Div-Tags sollen nicht im gesamten Dokument, sondern nur in dem Bereich aktiv sein, in welchem sie selbst platziert sind. Als Nebeneffekt werden auf diese Weise unter anderem auch keine Links einer Navigationsbar oder einer Menüstruktur berücksichtigt. Auf diese Weise kann man für einzelne Kapitel, zum Beispiel längere Blogartikel, eigene Verzeichnisse auf der gleichen Webseite erhalten.

Ein Abkürzungs-Verzeichnis erstellen
Wir wollen jetzt, exemplarisch für die anderen Verzeichnisse, die Erstellung eines Abkürzungsverzeichnisses erklären. Der JavaScript-Code für unsere Verzeichnisse befindet sich in der Datei jsDynListControls.js. Neben dieser Datei binden wir im Kopfteil der HTML-Datei die Dateien jsComponents.js und jsComponents.css ein. Siehe dazu das folgende Beispiel:

 <html> <head> <title>jsDynListAbbr - Example</title> <script type="text/javascript" src="jsc/jsComponents.js"> </script> <script type="text/javascript" src="jsc/extra/jsDynListControls.js"> </script> <link rel="stylesheet" type="text/css" href="jsc/jsComponents.css" /> </head> <body>

Die jsComponents-Dateien enthalten den Code für andere Komponenten, die auf einer Webseite einsetzbar sind, wie Tabboxen oder Tree-Komponenten. Der JavaScript-Code bietet außerdem einige Hilfsfunktionen, die das Laden unserer Verzeichnisse sicherstellen. Der Konstruktor für unsere Klasse, welche das Abkürzungsverzeichnis erstellt, heißt JSDynListAcronym und entsprechend brauchen wir unserem HTML-Code nur eine Zeile der Form

 <div class="JSDynListAcronym"> </div>

einzufügen, um diesen Konstruktor mit dem Div-Element als Argument aufzurufen.

Hier der HTML-Code für die Erstellung einer Abkürzungsliste:

 <h1>Latein-Text</h1> <h2>Lorem Ipsum</h2> <p>Lorem ipsum ne natum lorem dicit sea,  <acronym>nullam recteque (NE)</acronym> conceptam pri at, at sed porro bonorum. Labores placerat deserunt nec te, homero erroribus vis ut. Eum id tamquam gubergren, te falli nonumy antiopam eos. Ut sed quas evertitur. Nam id  <acronym>illud malorum (IM)</acronym> . Possit sanctus mel in, populo mediocritatem qui ne.</p> <h2>Deutscher Text</h2> <p>Eine <acronym>Abkürzung (Abk)</acronym> kann auch mehrfach im Text vorkommen so zum Beispiel diese <acronym>NE</acronym>. Sie wird aber nur bei der Deklaration in die Liste aufgenommen.</p> <h2>Abkürzungsverzeichnis</h2> <div class="JSDynListAcronym"> </div>

Nun zu unserem JavaScript-Code:

 function JSDynListAcronym (element) { var parent = element.parentNode; var abbrs = parent.getElementsByTagName("acronym"); var targetList = document.createElement("dl"); // RegExp speichern // Nur Einträge der Form "Text für die Abkürzung (Abk)" // wie bei erstmaliger Verwendung üblich werden berücksichtigt var rx = new RegExp("(.+)\\((.+)\\)"); var l = abbrs.length;  // Ein Array erstellen um später einfach zu sortieren var resList = new Array(); for (var x = 0 ; x < l ; x++) { var text = stringRemoveReturns(abbrs.item(x).innerHTML); var res = rx.exec(text); if (res) { resList.push(""+RegExp.$2+":::"+RegExp.$1); } } resList.sort(); var l2 = resList.length; // Nun Anhängen der Abkürzungen for (var x = 0 ; x < l2 ; x++) { var arr = resList[x].split(":::"); var dt = document.createElement("dt"); dt.appendChild(document.createTextNode(arr[0])); var dd = document.createElement("dd"); dd.appendChild(document.createTextNode(arr[1])); targetList.appendChild(dt); targetList.appendChild(dd); } element.appendChild(targetList) ; }

Der Code für diese Klasse ist nur etwa 30 Zeilen lang. Zuerst werden alle Abkürzungen im Eltern-Knoten, in dem sich unser Div-Tag der Klasse JSDynListAcronym befindet, nach dem Vorhandensein einer Acronym-Tags der Form Text (Abk) durchsucht. Für gewöhnlich werden Abkürzungen bei ihrem ersten Auftreten auf diese Weise in den Text eingeführt.

Durch die Verwendung eines solchen Tests wird die Nutzung des Acronym-Tags ermöglicht, ohne dass in jedem Falle ein Eintrag im Abkürzungsverzeichnis erfolgt. Außerdem kann man schnell eine doppelte Verwendung der Abkürzungsdeklaration durch einen Blick ins Abkürzungsverzeichnis festellen. Um eine sortierte Anzeige der Abkürzungen zu ermöglichen, werden diese in einem Array zwischengespeichert und anschließend alphabetisch sortiert. Danach wird jeder Eintrag des sortierten Array an die Definitionsliste im Dokument angehängt. Voila! Wichtig ist es zu wissen, dass der Internet Explorer einige Standard-HTML-Elemente nicht richtig behandelt, so verbietet sich aus diesem Grund zum Beispiel die Verwendung des Abbr-Tags, wenn man auf gut strukturierten Code Wert legt [IE ABBR-Hack]. Das Beispiel in der Praxis: jsdynlistacronym.html

Verzeichnis von Definitionen
Ganz ähnlich erfolgt das Erstellen eines Defintionsverzeichnisses. Definitionen werden in der Form: <dfn>Term: Definitionstext<dfn> im Text deklariert. Der JavaScript-Code ist analog zu unserem vorherigen Beispiel, nur werden jetzt Dfn-Elemente und ein anderer regulärer Ausdruck verwendet. Dabei kann der Doppelpunkt auch durch ein Komma oder durch ein Minuszeichen ersetzt werden.

Um ein derartiges Verzeichnis einzufügen, muss der Autor einen Div-Tag mit dem Klassenattribut JSDynListDfn an einer beliebigen Stelle im Dokument platzieren. Das Einbinden eines solchen Div-Elementes führt analog zu unserem Beispiel mit den Abkürzungen zum Erfassen sämtlicher Dfn-Elemente und bei einem positivem Test des regulären Ausdrucks zum Einbinden der Definition in unsere Liste. Hier der HTML-Code für die Erstellung einer Definitionsliste:

 <h2>Einige Beispieldefinitionen</h2> <p>Hier ist ein Absatz mit Definitionen. <dfn>Definition - beschreibt einen Begriff in eindeutiger Weise</dfn>. Ein <dfn>Abkürzungsverzeichnis - eine Liste mit im Text verwendeten Abkürzungen</dfn> - wird am Anfang oder Ende eines Artikels platziert um dem Leser eine Hilfe beim Verständnis des Textes zu bieten.</p> <h2>Definitionen</h2> <div class="JSDynListDfn"> </div>

Der aufmerksame Leser wird sich an dieser Stelle eventuell fragen, wie Definitionen in die Liste aufgenommen werden können, die (noch) nicht im Text erscheinen. Ein elegante Lösung ist es, diese in einem versteckten Div-Tag zu sammeln. Dazu muß dessen Style-Attribut auf display:none gesetzt werden. Das funktionierende Beispiel: jsdynlistdfn.html

Linkliste
Wenn man einen Artikel ausdruckt, ist es angenehm, die im Dokument verwendeten Links im Klartext, zum Beispiel am Ende des Textes, lesen zu können. Um eine solche Linkliste zu erstellen, gehen wir wie folgt vor. Die im Mutterknoten unseres magischen Div-Tags mit dem Klassenattribut JSDynListLink im Text vorhandenen Links auf externe Seiten, also A-Tags, deren Href-Attribut das Prefix http trägt, werden eingesammelt. Danach wird der Text innerhalb des Links durch eine fortlaufende Nummer ersetzt und die Links werden dann in der Reihenfolge ihres Auftretens in die Linkliste eingefügt. Bei dieser Prozedur erfolgt eine Überprüfung auf bereits vorhandene Einträge in der Linkliste. Für einen existierenden Eintrag wird die schon vorhandene Nummer eingefügt. Hier der HTML-Code, um eine solche Linkliste zu erzeugen:

 <h2>Link-Text</h2> <p>Für Informationen siehe bitte in der Wikipedia [<a href="http://de.wikipedia.org">Deutsche Wikipedia</a>] nach. Wir verwenden jetzt den Wikipedia-Link ein zweites Mal um zu sehen ob er mit der gleichen Nummer ausgestattet ist: [<a href="http://de.wikipedia.org">Deutsche Wikipedia</a>]. Es folgt ein Link auf die Laurem-Lipsum Seite [<a href="http://www.lipsum.com">Laurem-Seite</a>] und ein Link auf die jsComponents-Seite [<a href="http://www.dgroth.de">jsComponents-Webseite</a>] sowie ein interner <a href="../index.html">Artikel-Link</a> der in der Literaturliste nicht berücksichtigt werden sollte.</p> <h2>Externe Referenzen</h2> <div class="JSDynListLink"> </div>

Hier das Beispiel zum Testen: jsdynlistlink.html

Inhaltsverzeichnis
Bei der Erstellung eines Inhaltsverzeichnisses aus den Header-Tags wie h1, h2 oder h3 durchlaufen wir die nachfolgenden Zwillingsknoten (Siblings) unseres Div-Tags der Klasse JSDynListToc und überprüfen, ob einer der erwähnten Überschriften-Tags vorliegt. Um eine Hierarchie abbilden zu können, erzeugen wir entsprechend der Niveaus der Überschriften eine geschachtelte Liste. Dazu speichern wir in einem Array die jeweils letzten Knoten für jede Überschriften-Ebene, um Kindsknoten an die richtige Stelle in der Liste einhängen zu können.

Um von dem erstellten Inhaltsverzeichnis mittels eines Links an die dazugehörige Stelle im Text springen zu können, fügen wir jedem Überschriften-Tag ein Namen- und ein Id-Attribut hinzu. Es ist dabei zu beachten, dass nur Zwillingsknoten die auf unser Div-Tag folgen, berücksichtigt werden und dass die Knoten nur richtig gefunden werden, wenn die Überschriften ohne „Lücken“ verwendet werden. So werden H2-Knoten immer an den letzten H1-Knoten angehängt, H3 immer an den letzten H2-Knoten und so weiter. Das Niveau des Startknotens kann allerdings beliebig sein. Hier der etwas längere HTML-Code für das Beispiel: jsdynlisttoc-code.html. Und hier das Beispiel zum Testen: jsdynlisttoc.html

Literaturverzeichnis
Im Gegensatz zu den vorhergehenden Beispielen existiert das Literaturverzeichnis bereits bei der Erstellung des Dokumentes als geordnete Liste. Es kommt es jetzt darauf an, für jedes Zitat die Position in der vorhandenen Liste herauszufinden und die daraus resultierende Nummer in den Text einzusetzen.

Für Zitate im Text werden (natürlich) Cite-Tags benutzt. Im allgemeinen erfolgen Verweise auf Literaturstellen im Text entweder durch eine Angabe wie Name, Publikationsjahr oder durch fortlaufende arabische Zahlen. Letzteres bietet den Vorteil, dass man beim Lesen nicht durch die Autorennamen unterbrochen wird. Die Realisierung einer Nummerierung ist aber schwieriger, da sich die Nummern im Laufe der Manuskripterstellung fortwährend ändern.

Text wird eingefügt, werden andere Passagen wieder gelöscht. Um sich nicht mit der manuellen Vergabe der Nummerierung und deren ständiger Anpassung an eventuelle Änderungen der Dokumentstruktur auseinandersetzen zu müssen, wollen wir die Nummernvergabe an das Literaturzitat automatisieren. Zu diesem Zweck muss im HTML-Dokument eine Literaturliste als geordnete-Liste, also mit Ol-Tags, erstellt werden. Diese sind durch einen Div-Tag mit dem Klassenattribut JSDynListRef einzuschließen. Dazu ein Beispiel:

 <div class="JSDynListRef"> <ol> <li id="Meyer2007">Meyer, Otto. Ein Beispieltitel für den allgemeinen Gebrauch. Meyers Journal 7:8-11 (2007).</li> <li id="Mueller2006">Mueller, Fritz. Ein Beispieltitel für den allgemeinen Gebrauch von Mueller. Meyers Journal 5:12-14 (2006).</li> <li id="Mueller2006b">Mueller, Fritz. Muellers zweiter Titel aus dem gleichen Jahr. Allgemeines Journal 66:1-101 (2006).</li> </ol> </div>

Jetzt der Beispieltext, welcher auf diese Literaturzitate verweist:

 <div> Dies ist ein Beispieltext welcher verschiedene Literaturzitate wie die von Meyer [<cite>Meyer2007</cite>] benutzt. In der Vergangenheit hat auch ein anderer Autor mehrfach versucht sich durch solche Beispielzitate zu profilieren [<cite>Mueller2006,Mueller2006b</cite>]. Im JavaScript-Code muß sichergestellt werden, daß ein Zitat mehrfach aber mit der gleichen Nummer auftauchen kann. Dazu zitieren wir erneut unseren Meister des Beispiels [<cite>Meyer2007</cite>]. Eine mögliche Erweiterung könnte die Verlinkung der Zitate in die Liste sein. </div>

Das funktionierende Beispiel: jsdynlistref.html

Ausblick
Die hier vorgestellte automatische Verzeichnis-Erstellung ähnelt der von LaTex, bietet aber den Vorteil, dass keine neue Markup-Sprache erlernt werden muss und dass kein Compiler für das Erstellen des Dokumentes benutzt wird. Für längere Abhandlungen, die vor allem in gedruckter Form erscheinen sollen, ist sicher LaTex die bessere Wahl. Interessant wäre außerdem die Umwandlung des HTML-Codes in LaTex-Code. Dazu gibt es bereits Tools wie html2tex.

Auch die Erstellung von statischem HTML-Codes durch ein Tool wie die Mozilla JavaScript-Engine für Java – Rhino ist eine weitere Möglichkeit. Dem Leser fallen sicher noch weitere Verzeichnisse wie für Tabellen, Beispiele und Stichwörter als denkbare Erweiterungen ein. Hinweise zum Artikel werden gerne entgegen genommen (). ™

Erstveröffentlichung 02.08.2007

Dr. Detlef Groth

Dr. Detlef Groth, von Beruf Biochemiker und IT-Konsultant, arbeitet als Bioinformatiker und Autor in Potsdam und Umgebung.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.