scrollto infinite (mit jquery)

Ob der Begriff „inifinte scroll“ wirklich Sinn ergibt, sei mal dahin gestellt, aber bei Bings oder Googles Bildersuche hat man schon das Gefühl das es unendlich weitergehen wird.

Es geht darum, dass, sobald der Besucher einen bestimmten Seitenbereich erreicht (erscrollt) hat, automatisch weitere Inhalte geladen und in die Seite eingefügt werden – eine Art „Paginierung 2.0“.

Was man dazu braucht ist jQuery, ein bisschen Verständnis der Browser Events, eine „Spinner“ Grafik (das kommt aus dem englischen von spinning = rotieren) und natürlich Inhalt.

Die Spinner Grafik erstellet man einfach bei Ajaxload.info. Diese wird Hintergrundgrafik eines <div> mit der id „infiniteSpinner“.

#infiniteSpinner {
  backoground: transparent url(spinner.gif) center no-repeat;
  width: 100%;
  height: 16px;
  opacity: 0;
}

Das div#infiniteSpinner wird nach dem Element eingefügt, welches den unendlichen Inhalt beherbergt, also zum Beispiel nach dem ul#infinite.

Jetzt geht es schon mit Javascript weiter, das soll folgendes können:

  • Auf das Scroll-Event hören
  • erkennen wann das div#infiniteSpinner in den sichtbaren Bereich gescrollt wurde
  • dann das div#infiniteSpinner zeigen und einen AJAX Call starten
  • die AJAX Antwort verarbeiten, den neuen Inhalt in die Seite einfügen, bei jQuery < 1.5 müssen die Listener von allen Inhalten gelöscht und neu gesetzt werden
  • Aus der Ajax Antwort erkennen ob man den infinite-scroll Handler weiterhin gesetzt lassen muss, oder ob die Unendlichkeit schon erreicht wurde
  • Am Ende das div#infiniteSpinner wieder verstecken

Das Scroll-Event.

Unter Firefox oder Chrome kann man auf dem document Element das scroll-event abfangen, aber mindestens IE7 und IE8 wollen das scroll-event auf dem window element. Daher ergibt sich folgende Zeile:

var scrollTimer = null;
var scrollTimeout = 333;
// onload hook
$().ready(function(){
  $(window).scroll(function(){
    if (scrollTimer) {
      window.clearTimeout(scrollTimer);
      scrollTimer = null;
    }
    scrollTimer = window.setTimeout('infinitescroll()', scrollTimeout);
  });
});

So kriegt man jedes scroll-event mit. Den Timeout setzten wir, damit nachher nicht bei jedem Scroll die ganze Verarbeitung durchrattert, sondern erst 333ms nachdem letzten scroll-event. Ohne diesen Timeout würde man unnötig den Client strapazieren und auch eine kleine DOS-Attacke auf den eigenen Server starten.

Jetzt muss man feststellen ob das div#infiniteSpinner im sichtbaren Bereich des Nutzers ist. Auch hier spielen IE7 und IE8 ihr eigenes Spiel, daher nutzte ich zur Bestimmung der Scrollposition im Browser die Funktion getScrollXY() von Ajaxschmiede.de.

Der AJAX-Call kann dann so aussehen:

var ajaxRunning = false;

function checkScrollPos() {
  var zone = 30;
  var infiniteSpinnerY = $('#infiniteSpinner').offset().top;
  var scrollXY = getScrollXY();
  return ((scrollXY[1] + $(window).height()) - infiniteSpinnerY) <= zone ;
}

function infinitescroll() {
  if (ajaxRunning) return false;
  if (!checkScrollPos()) return false;
  $.ajax({
    data : { startOffset : $('#infinite').find('li').length },
    cache: false,
    beforeSend : function() {
      ajaxRunning = true;
      $('#infiniteSpinner').fadeTo('fast',1);
    },
    complete : function() {
      ajaxRunning = false;
      $('#infiniteSpinner').fadeTo('slow',0);
    },
    success : function(data) {
      if($(data).find('#lastinfinite').is('*')) $(window).unbind('scroll');
      $('#infinite').append($(data).find('#infinite').html());
    }
  });
}

Und das ist es schon.

Auf Serverseite sollte man die Ausspielung noch mit einer echten Blätterfunktion versehen, damit Suchmaschinen und nicht-JS-Clients die Inhalte erreichen können. Im dargestellten Beispiel wird zum Beispiel ein GET-Parameter startOffset mitgegeben, anhand dessen der Server die nächsten Ergebnisse ausspielen kann.
Außerdem sollte man auf der Serverseite schauen ob man nicht ein sinnvolles Caching innerhalb der Anwendung einsetzten kann.

Angenommen es handelt sich um eine Bildergalerie und auf jedem Bild wird noch ein click-event registriert, ist man mit jquery >= version 1.5 aus dem Schneider, da man dort einfach die $(‚#infinite‘).find(‚li img‘).live(‚click‘,function(){….}); nutzten kann.
Ist man allerdings in der Verlegenheit einem älteren Projekt dieses Feature zu spendieren, dann müsste man in dem success-callback nachdem an die neuen Inhalte eingefügt hat, erst alle click-Listener löschen und dann auf allen Elemente neu setzten.

Schreibe einen Kommentar

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