HaloScan Kommentare direkt auf der Blogseite anzeigen
Ausgangssituation
Der Seitentyp "Blog" hat in der Version 3.5 von RapidWeaver große große Verbesserungen erfahren. Trotzdem gibt es noch einiges zu verbessern. Mit dem Erscheien des Plugins RapidBlog, hatte ich schon all meine Wünsche erfüllt gesehen. Aber leider geht das Plugin in eine andere Richtung. Mir kommt es nicht so sehr auf die Möglichkeit an, auch von Unterwegs Blogeinträge erstellen zu können, sondern mehr um einer bessere Integration des Kommentarsystems. Ich will nicht von meiner Seite wechseln um Kommentare zu lesen oder zu erstellen. Einer der beiden Punkte ist im RapidBlog Plugin bereits gelöst. Die Kommentare werden direkt auf der Blogseite angezeigt. Doch beim Schreiben von Kommentaren sieht es mit der Blogspot-Seite irgendwie noch schlimmer aus. Ich möchte also weiterhin die Blogfunktionalität von RapidWeaver nutzen, aber trotzdem die Komentare direkt auf meiner Seite sehen.
Ziel
Die Kommentare zu einer RapidWeaver Blog, sollen direkt auf den Blogseiten angezeigt werden. Die Lösung soll in das Theme der Seite eingebettet werden und möglicht einfach für auf den Betroffenen Seiten aktiviert werden können.
Lösung
Einlesen des Kommentarfeed
Als Quelle für die Kommentare dient uns der Kommentarfeed, der von HaloScan bereitgestellt wird. Die XML Form des Feeds bietet die optimale Grundlage zur weiterverarbeitung der Daten. Mit Hilfe eines AJAX Requests können wir den Feed im Hintergrund ahbolen und mittels JavaScript weiterverarbeiten. Hier stoßen wir aber auch schon auf das erste kleine Problem. Aus Sicherheitsgründen kann man mittels AJAX keine URL's aufrufen, die Außerhalb der aktuellen Domain liegen. Um dieses Problem zu lösen, schreiben wir uns zunächst ein kleines Proxy-Script z.B. in PHP. Da das Script nur den Feed von der entfernten URL abrufen und durchreichen muss, ist die Programmierung kein großes Problem.
<?phpheader("Content-type: text/xml");readfile("http://www.haloscan.com/members/rss.php?user=" . $_GET["user"]);?>
Derzeit habe ich mich dafür entschieden das Proxy-Script als Seitenanlage (Asset) an die Blogseite zu hängen (In den "Seiten-Informationen" unter "Erweitert"). Ich habe aber schon mehrmals überlegt das Proxy-Script fest in der Theme-Datei unterzubringen.
Kommentar-Feed per AJAX abholen
Mit Hilfe des Proxy-Scripts können wir jetzt den Kommentar-Feed per AJAX-Request abholen. Zum Einsatz kommt dabei wieder die Prototype Library in der Version 1.5, die neben der AJAX-Unterstützung auch noch zahlreiche Funktionen mitbringt, die wir beim Umgang mit dem HTML Elementen gut gebrauchen können. Um die Prototype Library zu verwenden, muss diese natürlich in das Theme eingefügt werden. Hierzu sind folgende Dinge notwendig:
- Hinzufügend der "prototype.js" zur Theme-Datei
- Einbinden der Datei im Header der index.html des Themes
- Angeben der Datei im "RWCopyFiles"
Das Script zum Abholen des Fedds ist auch noch sehr übersichtlich. Anhand der Existenz von HTML Elementen mit der Klasse "blog-archive-entries-wrapper", ob es sich bei der aktuellen Seite um die Hauptseite des Blogs handelt, oder um eine der Archiv-/Detailseiten. Abhängig davon wird der relative Pfad zum Proxy-Script gesetzt. Naschließend wird der AJAX-Request erzeugt. Als Parameter erhält dieser die Funktion, die im Erfolgsfall aufgerufen werden soll.
function getHaloComments() {var content = $('content');// Der Pfad zum Proxy-Script ist abhaengig davon, ob wir auf der Hauptseite des Blogs sind,// oder z.B. auf einer Archiv Seite. Nur auf Archivseiten existieren Container mit der// Klasse 'blog-archive-entries-wrapper'.var blogEntries = content.getElementsByClassName('blog-archive-entries-wrapper');var requestUrl;if (blogEntries.length > 0) {requestUrl = '../assets/haloscan.php';}else {requestUrl = 'assets/haloscan.php';};// Abrufen des Kommentar-Feeds mittels AJAX Request.var haloAjax = new Ajax.Request(requestUrl,{method: 'get',parameters: 'user=niedral',onComplete: addHaloComments,onFailure: function(){ alert('Something went wrong...')}});}
Zuordnen und Einfügen der Kommentare
Jetzt kommt der schwierigste Teil. Die eingelesene XML
Datei muss abgearbeitet werden, und aus den relevanten
Informationen müssen die Kommentare generiert und eingefügt
werden. Vom AJAX-Request
bekommen wir ein DOM-Objekt
der eingelesenen XML-Datei übergeben, auf das wir mit
den entsprechenden JavaScript bzw. Prototype Funktionen
zugreifen können. Auf diese Weise übertragen wir
zunächst alle Kommentare in ein Hilfsarray/-objekt,
wobei nur die Kommentare übertragen werden, die zur
aktuellen Blogseite gehören. Die ID der aktuellen
Blogseite, anhand derer wir die Kommentare ausfoltern,
wird später als globale Variable definiert. Mit dem
Hilfsarray/-objekt simuliere wir ein assoziatives Array,
in dem die Kommentare nach Blogeinträgen zusammengefasst
abgelegt werden. Da es bei JavaScript eigentlich keine
assoziativen Array gibt, werden diese mit Hilfe von
Objekten simuliert, so wie es im Artikel "Assoziative Arrays" auf SELFHTML beschrieben ist. Wahlweise
könnte man an dieser Stelle auch das Hash Objekt der Prototype
Library verwenden, das ebenfalls ein assoziatives
Array nachbildet.
Nachdem die Kommentare herausgefiltert wurden suchen wir
die Blogeinträge der Seite heraus und ordnen diesen die
Kommentare zu. Für jeden Kommentar werden die benötigten
HTML Objekte erzeugt und an den Blogeintrag angehängt.
function addHaloComments(originalRequest) {// Kommentare aus dem XML Response heraushohlen.var xmlResponse = originalRequest.responseXML;var items = xmlResponse.getElementsByTagName('item');// Alle Kommentare überprüfen und gegebenenfalls zwischenspeichern.var feedComments = new Object();var commentTitle, commentLink, commentDescription;var commentPageId, commentId;for (i = 0; i < items.length; i++) {for (j = 0; j < items[i].childNodes.length; j++) {var node = items[i].childNodes[j];switch (node.nodeName) {case "title":commentTitle = node.firstChild.nodeValue;break;case "link":commentLink = document.createTextNode(node.firstChild.nodeValue);break;case "description":commentDescription = document.createTextNode(node.firstChild.nodeValue);break;};};// Mittels Regulaerem Audruck die ID's der Seite und des Blogeintrages, sowie den Namen// des Posters aus dem Titel des Kommentars extrahieren.var expression2 = /^Thread: rw unique entry id (\d+) (page\d+)\. Post by (.+)$/;expression2.exec(commentTitle);commentId = RegExp.$1;commentPageId = RegExp.$2;// Gehoert der Kommentar zur aktuellen Seite?if (commentPageId == pageId) {// Falls nicht vorhanden, ein Array fuer die Kommentare des aktuellen Blogeintrags anlegen.if (!feedComments[commentId]) {feedComments[commentId] = new Array();};// Aktuellen Kommentar in einem Hilfobjekt speichern und das Objekt speichern.var currComment = new Object();currComment["title"] = "Kommentar von " + RegExp.$3;currComment["description"] = commentDescription;currComment["link"] = commentLink;feedComments[commentId].push(currComment);};};// Blogeintraege aus dem Inhalt der Seite heraussuchen.var content = $('content');var blogEntries = content.getElementsByClassName('blog-entry');for (var i = 0; i < blogEntries.length; i++) {// Nummer des Blogeintrages aus dem id Attribut extrahieren.var id = blogEntries[i].id;var entryId = id.substring(16, id.length);if (entryId != "") {// Sind Kommentare vorhanden?if (feedComments[entryId]) {// Neuen Kommentar-Container erzeugen.var comments = document.createElement('div');comments.className = "comments_container";// Fuer jeden Kommentar die benoetigten HTML Elemente anlegen.for (j = 0; j < feedComments[entryId].length; j++) {var titleContainer = document.createElement('div');titleContainer.className = 'comment_title';var titleNode = document.createTextNode(feedComments[entryId][j]["title"]);titleContainer.appendChild(titleNode);var descriptionContainer = document.createElement('div');descriptionContainer.className = "comment_description";descriptionContainer.appendChild(feedComments[entryId][j]["description"]);var comment = document.createElement('div');comment.className = "comment_container";comment.appendChild(titleContainer);comment.appendChild(descriptionContainer);comments.appendChild(comment);};// HTML Elemente beim Blogeintrag anhängen.blogEntries[i].appendChild(comments);};};};}
Verwendung
Um das Ganze nun wirklich verwenden zu können müssen die
beiden JavaScript Funktionen in die "javascript.js"-Datei
des Themes eingefügt werden. Um die Funktionen automatisch
aufzurufen sobald die Seite geladen wurde, ist noch ein
"onLoad" mechanismus notwendig. Da es unter Umständen noch
weiter Funktionen gibt auf die das ganze zutrifft, verwende
ich wieder eine Funktion, die ich mir beim Rico
Projekt abgesehen habe. Ein ausführliche Beschreibung
ist in meinem "RapidWeaver
- Lightbox" Tutorial zu finden, wo ich den
Mechanismus bereits verwendet habe.
Anschließend sind in RapidWeaver
noch einige Ergänzungen an der Blogseite selbst
notwendig. Das Proxy-Script muss als "Seitenanlage"
unter "Erweiter" in den "Seiten-Information" der
Blogseite hinzugefügt werden. Außerdem müssen unter
"Code" in den "Seiten-Informationen" der Blogseite
folgende Angaben in Feld "Eigenes JavaScript" angegeben
werden:
var pageId = 'pageXX';onloads.push(getHaloComments);
Die erste Zeile setzt die globale Variable mit der
Page-ID der Blogseite, die zum herausfiltern Kommentare
verwendet wird.
Die zweite Zeile sorgt dafür, dass der Kommentarimport in
den "OnLoad" Mechanismus aufgenommen wird.
Wenn alles klappt werden die Kommentare kurz nach dem Laden
der Seite unterhalb der Blogeinträge angezeigt.
Fazit
Mit Hilfe dieser Lösung kommt man dem richtigen
Blog-Feeling wieder einen Schritt näher. Nachteil ist
natürlich, das die Kommentare z.B. für Suchmaschinen nicht
sichtbar sind. Ich denke aber, das der Seitentyp Blog in
den kommenden Versionen von RapidWeaver
weitere verbesserungen erhalten wird. Und wenn nicht,
finde ich ja vielleicht doch noch einmal die Zeit, um
micht in die Mac/RapidWeaver Programmierung
einzuarbeiten und mir meine eigenes Blog Plugin zu
bauen.
Ich hoffe auch dieses Tutorial trifft wieder den geschmack
einiger RapidWeaver
Benutzer und würde mich über Resonanz im zugehörigen
Blog-Eintrag oder über das
Kontaktformular freuen.