Mittwoch, 14. April 2010

Automatischer Index mit jQuery

Die Arbeit mit jQuery spart Zeit, die man wunderbar für Schnickschnack nutzen kann. Obwohl... eigentlich ist so ein Index bei langen Texten ganz schön praktisch.
Nach dem absatzweisen Scrollen zur Erhöhung des Lesegenusses ;O) werden nun lange Texte automatisch indiziert und über eine Sidebar navigierbar (Beispiel). Auch hier verwenden wir jQuery und das scrollto-Plugin.

Verbesserung der Event-Behandlung

Die bisherige Event-Behandlung hat einen Nachteil: Zwar wurde der Timerevent bei mouseup ordentlich abgeschaltet, aber der Event war weiter an die Funktion gekoppelt. Gaanz schlecht... Denn dann können andere UI-Elemente auf der Site nicht mehr benutzt werden. Wie gesagt: Gaanz schlecht.
Also wird erstmal die endscroll-Funktion verbessert:

// alte Version
function endscroll() {
 if (typeof(scroll_timeout) != "undefined"){
  clearTimeout(scroll_timeout);
 }
 if(hipara) {
  $('.scroll_'+aktpara).addClass('hilite');
 }
 oldakt = aktpara;
}

// neue Version
function endscroll() {
 if (typeof(scroll_timeout) != "undefined"){
  clearTimeout(scroll_timeout);
 }
 if(hipara) {
  $('.scroll_'+aktpara).addClass('hilite');
 }
 oldakt = aktpara;
 $(window).unbind('mouseup'); //important change to elder versions: unbind to release events to other ui elements
}
Damit ist der mouseup-Event wieder für andere Elemente freigegeben.

Der Index

Nun soll ein automatischer Index der Absätze erstellt werden. Jeder Eintrag dieser Liste enthält den Anfang des Absatzes und die laufende Nummer. Die Einträge sind anklickbar und steuern den Hauptinhalt (scrollcontent) an die gewünschte Stelle. Über die Scroll-Tasten werden die beiden Elemente scrollcontent und index bewegt. Und zu guter Letzt muss auch das Highlighting auf beide Container angewendet werden.
Absätze ermitteln
Die neue Funktion makeindex erstellt die Liste der Absätze und weist jedem Eintrag den Event zu.
Zuerst definieren wir ein paar shortcuts, die Tipparbeit sparen:
function shmakeindex () {
 // shortcuts
 var scc = $('#scrollcontent'); 
 var idx = $('#index');
 var prf = '.scroll_';      // prefix
    var txt = new Array(paras.length);
 var wl = new Array();
 var str = "";
Damit sind die Vorarbeiten erledigt. paras ist übrigens global und wird bei der Initialisierung gesetzt. Das könnte man natürlich auch als Parameter übergeben, was wohl der bessere Stil wäre. Aber da diese scroll-Skripte aufeinander aufbauen, hat es sich so ergeben...
Absatzanfänge einsammeln
Weiter. Die Absatzanfänge werden nun wortweise mit einem regulären Ausdruck ermittelt und im Array wl gespeichert. Von diesen behalten wir dann die ersten sechs (willkürlich ;O), kleben sie mit etwas join™ zusammen und speichern sie im txt-Array:
// cut off some text from beginning of para
 paras.each( function(index) {
     str = $(this).text();
     wl = str.split(/\b/g);   // split into words
     wl = wl.slice(0,6);      // keep first six
     txt[index] = '<li><span class="scroll_'+index+'">'+ wl.join('') + '...</span></li>';  // classname for nav.
    });
 // build index
 idx.html('<p style="font-size:10px; margin-left:1em;"> ¬
   Navigation mit automatisch erstelltem Index</p><ol>'+txt.join('')+'</ol>');
 // select lines
 var ele = $('#index span');
Hier wurde also die Liste der Absatzanfänge erstellt, pro Eintrag mit einem fortlaufenden Klassennamen 'indiziert' und an den Container übergeben.
Event-Behandlung
Jetzt heften wir einen Eventhandler an jeden Eintrag und sind fertig:
// attach eventhandling to every element
 ele.each(function(index){
       $(this).click(function(){
           oldakt = aktpara;
          aktpara = index;          
          if (hipara) {
           $(prf+oldakt).removeClass('hilite');
           $(prf+aktpara).addClass('hilite');
          }
          var dist = Math.abs(aktpara-oldakt);
          scc.scrollTo($('#scrollcontent '+prf+index),100*dist,{ axis:"y", offset:-64});
          oldakt = aktpara;
         });
       });
} //end shmakeindex
Dank jQuery alles gar nicht so komplimiziert...
Viel Spaß mit der Demo (gleich hilite aktivieren, dann wird das mit der Navigation klarer :)

Keine Kommentare: