JavaScript/Tutorials/Auto-Footnoter

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Fußnoten gehören nicht zu den typischen Elementen des reinen Webdesigns. Das hat mehrere Gründe.

  1. Webseiten sind nicht unterteilt (paginiert).
  2. Mit den heutigen Möglichkeiten des dynamischen HTMLs kann kurzfristig Anzuzeigendes am Ort eingeblendet werden.
  3. In typischen Webinhalten ist das Dokumentieren von Quellen weit weniger verbreitet als in der wissenschaftlichen Literatur.
  4. Software zur Herstellung von Webseiten ist nicht auf Fußnoten vorbereitet.

Dennoch kann es geschehen, dass Fußnoten gefragt sind. Immer häufiger werden gedruckte Werke auch online publiziert. Dabei müssen die Fußnoten aus den Druckwerken übernommen werden.

Fußnoten mittels JavaScript generieren[Bearbeiten]

Das händische Generieren von Fußnoten im Web ist aufwändig und fehleranfällig. Hier möchte ich eine Lösung zeigen, welche mittels JavaScript Elemente mit einer definierten Klasse als Fußnoteninhalte erkennt, diese zusammenträgt und an einem definierten Ort ausgibt. Dabei soll eine bidirektionale Verlinkung erstellt werden. Weil im Web das Einblenden von Inhalten in diesem Fall günstig ist, werden zusätzlich auf Wunsch Hovernotes generiert, wie das auch bei besseren Textverarbeitungen der Fall ist.

Diese Methode erlaubt Ihnen, im Original Notizen im Kontext zu schreiben. Sie haben dabei die Schwierigkeit und Freiheit, semantisch sinnvolles Markup zu erzeugen. Falls Javascript deaktiviert ist, verbleiben jedoch die Notizen in diesem Kontext. Sie können mit Hilfe einer Klasse auch bei deaktiviertem JavaScript solche Inhalte etwas absetzen, zum Beispiel durch eine etwas kleinere oder ausgegrauten Schrift oder etwa einem farbigen Hintergrund.

Das beiliegende CSS macht ihnen einen Vorschlag, wie Fußnoten bei deaktiviertem JavaScript angezeigt werden können.

JavaScript[Bearbeiten]

Der folgende JavaScript-Code besteht im Wesentlichen aus zwei Funktionen: Eine Funktion generiert die Fußnoten, die andere erzeugt Hovernoten.

autoFootNoter.js wird am Ende des HTML-body eingebunden. Sie können die zwei Funktionen aber auch ganz einfach in Ihre Library integrieren.

Beispiel
Die erste Funktion muss am Ende einmal aufgerufen werden.

Sie beginnt mit einem Konfigurationsabschnitt mit hoffentlich selbstsprechenden Variablen.

Die Variable footnotifyElementsByCssSelector enthält einen CSS-Selector, wie Sie Ihn auch in einem CSS-File notieren würden. Er wird der Methode querySelectorAll() übergeben.
function autoFootNoter(){
   /* START KONFIGURTATION */
   var footnotifyElementsByCssSelector = "body .fn",
      appendFootnoteCollectionToElementById = "examplecontent",
      footnoteCollectionId = "footnotes",
      footnoteCollectionHeadingAsHTML = "<h3>Fussnoten</h3>",
      footnoteAnchorIdPrefix = "fna",
      footnoteIdPrefix = "fn",
      showHovernotes = true;
   /* END KONFIGURTATION */
Der folgende Scriptabschnitt sammelt alle Elemente der definierten Klasse. Zum Einsatz kommt die neue DOM-Methode querySelectorAll(), welche eine statische Node-Liste zurückgibt.
   if(!document.querySelector){ return; }
   var f = document.querySelectorAll(footnotifyElementsByCssSelector);
Es wird ein Element für die Fußnoten-Sammlung kreiert. An dieses wird auch die Fußnoten-Überschrift angehängt.

Zusätzlich wird ein Element erzeugt, das später als Hovernote dienen soll. Es wird dem body-Element angehängt.

Es ist wichtig, dass wir hier ein Element via DOM-Methoden erzeugen und anhängen, und nicht etwa via innerHTML. Letzteres war für den Entwickler Anlass aufwändiger Fehlersuche.
   if(f){
      var col = document.createElement("div");
         col.id = footnoteCollectionId;
         col.innerHTML = footnoteCollectionHeadingAsHTML;
      var hnote = document.createElement("div");
         hnote.id="hovernote";
         document.getElementsByTagName("body")[0].appendChild(hnote);
Es wird nun jedes Element der statischen Node-Liste behandelt.

Bei einer statischen Nodeliste iterieren wir im Falle der Entfernung von Nodes anders, als wir das bei live-Nodelisten tun.

Der Fußnoten-Sammlung wird der Inhalt mit einem Backlink angehängt. Dabei wird das ursprüngliche Element in der Original-Fußnote zugunsten eines neutralen div-Elements getilgt.

Anschließend wird der Anker-Link mit id generiert. Er soll anschließend die originale Fußnote der Collection ersetzen.
      for(var i=0, j=1; i< f.length; i++, j++ ){
         col.innerHTML += '<div><a href="#' + footnoteAnchorIdPrefix + j
            + '" id="' + footnoteIdPrefix + j + '">' + j + '</a> <div>'
            + f[i].innerHTML+'</div></div>';
         var a = document.createElement("a");
            a.id = footnoteAnchorIdPrefix+j;
            a.href = '#'+footnoteIdPrefix+j;
            a.innerHTML=j;
Falls Hovernoten erwünscht sind, werden dem erzeugten Anker drei Eventhandler angehängt. Zwei Handler sind nur für das Verbergen zuständig. Der onclick-Handler ist wegen einem Bug in Opera notwendig.
         if(showHovernotes){
            a.title = ""; // Opera title stört bei Hovernotes
            a.onmouseover = function(event){ hoverNote(this,event);};
            a.onclick = function(){ hoverNote(); };
            a.onmouseout = function(){ hoverNote(); };
         }
Zuletzt wird die originale Fußnote durch den erzeugten Link ersetzt. Anders als bei einer Live-Nodeliste wird bei einer statischen Nodeliste durch replaceChild nicht der Knoten aus der Liste gelöscht, sondern es wird nur das DOM verändert. Die gesamte Fußnotensammlung wird nun an das definierte Element angehängt.
         f[0].parentNode.replaceChild(a, f[0]);
      }
      document.getElementById(appendFootnoteCollectionToElementById).appendChild(col);
   }
}
Die zweite Funktion wird durch die den Fußnotenankern angehängten Handler aufgerufen.

Wie immer muss das event-Objekt browserübergreifend abgefragt werden.

Die Position des Hovernote-Elements nahe dem Eventereignis im Fußnoten-Ankerlink bedingt, dass die Hovernote via CSS fixiert positioniert ist.
function hoverNote( el, evt ){
   var h = document.getElementById('hovernote');
   if(!evt) evt = window.event;
   if(el){
      var i = el.hash.substr(1,el.hash.length);
      h.innerHTML = document.getElementById(i).parentNode.innerHTML;
      h.style.display="block";
      h.style.left=(evt.clientX*0.7-10)+'px';
      h.style.top=(evt.clientY+15)+'px';
   }
   else{
      h.style.display="none";
      h.innerHTML ="";
   }
}
Zuletzt rufen wir die Funktion einmal auf.
autoFootNoter();

HTML[Bearbeiten]

Beim HTML handelt es sich um ein übliches (X)HTML-Dokument. Es soll hier gezeigt werden, wie im HTML nun Fußnoten definiert werden.

Die zu verarbeitenden Fußnoten werden durch den der querySelectorAll-Methode übergebenen CSS-Selector gefunden. Sie sind also nicht auf eine bestimmte Klasse für Fußnoten beschränkt. Es ist jedoch gut, allen Fußnoten im Originaltext eine einheitliche Klasse zu geben.

Sie können Whitespace vor und nach der Fußnote verwenden, um ihr Markup übersichtlich zu halten. Whitespace zwischen einem Stichwort und dem nachfolgenden erzeugten Anker wird durch CSS durch negative margins kompensiert.

<p>hier ist das Fußnoten-Stichwort
  <span class="fn">Fussnoteninhalt</span>
gefolgt von weiterem Text.</p>
Beispiel
Die Freiheit bezüglich dem Fußnotenelement gehorcht der Angabe des CSS-Selectors, den Sie im Javascript definieren. Am Besten verwenden Sie eine Klasse und behalten so Freiheit über das im Moment angemessene semantisch korrekte Fußnoten-Element. In den folgenden Beispielen wird die Klasse class="fn" verwendet.
<p>Dies ist eine Fußnoten-Demo zum autoFootNoter.js
<small class="fn">
 It's free as in <em>free beer</em> and <em>free speech</em>.
</small>.</p>
Sie haben vollkommene Freiheit, welche Elemente Sie verwenden. Im obigen Beispiel wurde ein small-Element verwendet.
<div>Fussnoten können auch Tabellen enthalten: Dieses Mini Sudoku
<div class="fn">
Dieses abgespeckte Mini-Sudoku zeigt das Prinzip.
<table style="border:1px solid black; width:100px; text-align:center">
<tr>
  <td style="color:red">1</td>
  <td style="color:red">2</td>
  <td style="color:blue">3</td>
  <td style="color:blue">4</td>
</tr>
<tr>
  <td style="color:red">3</td>
  <td style="color:red">4</td>
  <td style="color:blue">2</td>
  <td style="color:blue">1</td>
</tr>
<tr>
  <td style="color:green">4</td>
  <td style="color:green">3</td>
  <td style="color:black">1</td>
  <td style="color:black">2</td>
</tr>
<tr>
  <td style="color:green">2</td>
  <td style="color:green">1</td>
  <td style="color:black">4</td>
  <td style="color:black">3</td>
</tr>
</table>
Vertikalen, Horizontalen und Binnenquadrate müssen jeweils 
die Ziffern 1 bis 4 einmalig beinhalten</div><!-- end .fn --> 
ist korrekt<br></div>
Im obgen Beispiel wurde eine ganze Tabelle innerhalb der Fußnote notiert.

CSS[Bearbeiten]

Das CSS zeigt eine typische Fußnoten-Gestaltung.

Beispiel
/* Fussnotenspezifisch Anweisungen */

/* Original-Fussnoten, falls nicht mit JS ersetzt */
.fn {
   font-size:12px; 
   display:inline-block; 
   vertical-align:top;
}

/* die zu erzeugenden Fußnotenanker */
a[id^="fna"]{
   vertical-align:top;
   font-size:12px; 
   padding:0 2px 0 0;
   margin-left:-3px;   /* kompensiere Whitespace vor der Fußnote */
}

/* Die Fußnoten in der Sammlung */
#footnotes { 
   margin-top:1em; 
   font-size:14px; 
}
#footnotes h3 { 
   margin:0;
   font-size:16px;
   line-height:2;
   width:20em; 
   border-top:1px solid #ccc; 
}
#footnotes > div{
   padding:0 0 5px 40px;
   text-indent:-40px;
}
#footnotes > div > *{
   text-indent:0;
}
#footnotes > div > a:first-child{
   display:inline-block;
   width:30px;
   font-size:12px; 
   vertical-align:top;
   text-align:right;
}
#footnotes > div > div{
   width:auto;
   display:inline-block;
}

/* Die hovernote */
#hovernote{ 
   position:fixed; 
   display:none; 
   padding:5px; 
   font-size:14px; 
   background:#fff;
   -moz-box-shadow: 2px 4px 10px #666;
   -webkit-box-shadow: 2px 4px 10px #666;
   box-shadow: 2px 4px 10px #666;
}

Live-Beispiel[Bearbeiten]

Beispiel ansehen …
...(Link oben rechts)...