[GELÖST] nachgeladenen Inhalt anzeigen

J

j-l-n

Guest
Ich arbeite - wie auch schon in anderen Threads erwähnt - zurzeit an einem Chat.
Zum Nachladen von Nachrichten verwende ich folgendes:
Code:
var xmlhttp = false;
var xmlhttp2 = false;

function ajax_read(url) {
	if(window.XMLHttpRequest){
		xmlhttp=new XMLHttpRequest();
		if(xmlhttp.overrideMimeType){
			xmlhttp.overrideMimeType('text/xml');
		}
	} else if(window.ActiveXObject){
		try{
			xmlhttp=new ActiveXObject("Msxml2.XMLHTTP");
		} catch(e) {
			try{
				xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
			} catch(e){
			}
		}
	}

	if(!xmlhttp) {
		alert('Cannot create an XMLHTTP instance');
		return false;
	}

	xmlhttp.onreadystatechange = function() {
	if (xmlhttp.readyState==4) {
		document.getElementById("content").innerHTML = xmlhttp.responseText;

		zeit = new Date(); 
		ms = (zeit.getHours() * 24 * 60 * 1000) + (zeit.getMinutes() * 60 * 1000) + (zeit.getSeconds() * 1000) + zeit.getMilliseconds(); 
		intUpdate = setTimeout("ajax_read('chat-daten.txt?x=" + ms + "')", waittime)
		}
	}

	xmlhttp.open('GET',url,true);
	xmlhttp.send(null);
}


function ajax_write(url){ //diese Funktion ist eigentlich zum Absenden einer Nachricht da, ich poste sie aber trotzdem gleich mit

	if(window.XMLHttpRequest){
		xmlhttp2=new XMLHttpRequest();
		if(xmlhttp2.overrideMimeType){
			xmlhttp2.overrideMimeType('text/xml');
		}
	} else if(window.ActiveXObject){
		try{
			xmlhttp2=new ActiveXObject("Msxml2.XMLHTTP");
		} catch(e) {
			try{
				xmlhttp2=new ActiveXObject("Microsoft.XMLHTTP");
			} catch(e){
			}
		}
	}

	if(!xmlhttp2) {
		alert('Cannot create an XMLHTTP instance');
		return false;
	}

	xmlhttp2.open('GET',url,true);
	xmlhttp2.send(null);
}
Das ganze wird in einem div mit feste Höhe und overflow=auto angezeigt. Kommt nun eine neue Nachricht hinzu, wird diese nicht angezeigt, man muss erst nach unten scrollen, um sie zu sehen - wobei man natürlich nicht merkt, ob eine neue denn überhaupt vorhanden ist.
Wie muss ich den Code nun erweitern, dass (NUR WENN NEUER INHALT VORHANDEN IST) der div sich automatisch nach unten scrollt oder die Nachricht so eingefügt wird, dass sie automatisch sichtbar ist und dafür die alteb Nachrichten "nach oben schiebt"?
Zurzeit habe ich die - ebenfalls bekannte - Autoscroll Lösung, die alle 200ms automatisch scrollt. Dies ist allerdings nur eine Notlösung und daher bitte ich darum, mir zu helfen, wie ich das oben beschriebene Problem lösen kann!
 
Zuletzt bearbeitet von einem Moderator:
Ein globales XHR-Objekt ist nie eine gute Idee - v.A. wenn sie komplett überflüssig sind. Aber das nur am Rande.

Zu deinem Problem: wie man ein Element komplett nach unten scrollt, weißt du ja schon. Das Gleiche kannst du ja einfach machen, nachdem du das neue HTML an .innerhTML zugewiesen hast.
 
Das Gleiche kannst du ja einfach machen, nachdem du das neue HTML an .innerhTML zugewiesen hast.

Also so?
Code:
...
if (xmlhttp.readyState==4) {		document.getElementById("content").innerHTML = xmlhttp.responseText;
autoscroll(); //Funktion aufrufen
...

Da ist dann nämlich leider der gleiche Effekt: es scrollt nämlich immer und es springt auch dann, wenn man selbst gerade scrollt...

Auf das andere werde ich eingehen, wenn wir das gelöst haben. Danke aber schonmal für den zusätzlichen Hinweis!
 
Nicht die autoscroll() Funktion mit seinem Interval/Timeout aufrufen, sondern die Funktionalität, die darin verbaut ist. Also dem .scrollTop den Wert von .scrollHeight zuweisen.
 
Nicht die autoscroll() Funktion mit seinem Interval/Timeout aufrufen, sondern die Funktionalität, die darin verbaut ist. Also dem .scrollTop den Wert von .scrollHeight zuweisen.

Allerdings ist in der Autoscroll-Funktion gar kein Intervall. Das wird in einer anderern festgelegt, Resultat bleibt immer noch das gleiche...
 
Wie oft rufst du denn die ajax_read auf? Die darfst du natürlich nur aufrufen, wenn etwas neues vorliegt...
 
Du musst das pollen logisch von dem verarbeiten trennen. Das heißt, das Serverscript muss ein Flag liefern, das sagt, ob neue Daten folgen oder nicht. Und nur wenn neue Daten folgen darf die Funktion ausgeführt werden, die diese in das Chat Fenster gibt und scrollt. Am einfachsten wäre das, wenn du als Datenformat JSON verwenden würdest, dann könntest du dafür einfach ein Feld mitgeben. Kann man aber auch anders lösen, indem man z.B. das erste Zeichen dafür reserviert.
 
Ich blicke da leider wenig durch. Hat jemand vielleicht ein Codebeispiel, wie so etwas funktioniert?
 
Das hat eher mit Logik denn mit Code zu tun. Das Serverscript muss dem Browserscript sagen, ob Daten neu sind oder nicht. Und daraufhin muss das Browserscript entsprechend "handeln".
 
Ja schon, aber wie bekomme ich es dann hin, zu prüfen, ob in chat-daten.txt neuer Inhalt ist?
 
Ich mache das mit Timestamp. Das heißt, in die chat.txt wird zu jeder Nachricht ein Timestamp gespeichert. Und bei jedem Poll muss der Client den Timestamp liefern, wann er die letzte Nachricht dem Benutzer angezeigt hat. Das Serverscript schaut nach, ob es Nachrichten gibt, die danach gekommen sind. Wenn ja: Liefere an den Client Flag "ja" und dahinter die neuen Nachrichten. Wenn nein: Liefere an den Client nur Flag "nein".
Und der Client zeigt bei Flag "ja" eben die neuen Nachrichten an, scrollt und aktualisiert seinen Timestamp Zeiger. Bei Flag "nein" startet es einfach das nächste Inveral zum nächsten Polling ohne irgendwas an der Anzeige zu ändern.

Du brauchst also im Grunde drei Felder: Flag Neue Nachricht (nur im Response), Timestamp (nur im Request) und Nachrichten selbst (nur im Response). Die Nachrichten selbst wiederum benötigen n Felder, wobei jedes Feld wiederum aus Timestamp und Nachricht besteht. In JSON wäre das wunderbar mit einem Objekt darstellbar.
 
Zuletzt bearbeitet:
Du speicherst deine Chatnachrichten in einer TXT-Datei? Ich bezweifle stark, dass das jemals sauber laufen wird. Speicher die Nachrichten doch in einer Datenbank, dann kannst du viel schneller und leichter nur die neuen Nachrichten bestimmen und ausliefern.
 
Korbinian, das geht wunderbar. Man muss nur das Einmaleins des Dateihandlings beachten, von wegen flock & Co.
 
Würde denn es funktionieren, wenn ich mit timestamp arbeite und das Änderungsdatum vergleiche?
 
Julian, genau das habe ich doch in Beitrag 12 geschrieben. Das macht aber nicht der Browser sondern der Server und der setzt dann das entsprechende Flag für den Browser. Der Browser sendet im Request immer nur seinen letzten bekannten Timestamp. Und der Server schaut nach, ob es was neueres als das gibt und liefert dann im Response das neue.
 
Aber wenn ich zu jeder Nachricht einen Timestamp in der chat.txt Speichers, wird mir dieser doch dann auch immer für den User angezeigt?!
Dann steht da z.B.

Name - Nachricht 09-09-2009
 
Ja, dann hast du ein Problem mit der Datenstruktur auf dem Server. Deshalb ist eine Textdatei normalerweise auch nicht geeignet für einen Chat. Du brauchst zwingend mindestens 3 Felder pro Message: Timestamp, User-ID und Text.
Wenn du weiter mit Textdatei arbeiten willst musst du dir dafür ein Trennzeichen ausdenken, das niemals im Text vorkommen kann, z.B. Hex 00 oder 01 oder was auch immer. Und als Satztrennung z.B. das Newline oder carriage Return. Am allerbesten wäre, dem Rat mit der Datenbank zu folgen, da geht sowas nämlich etwas einfacher.
 
Gut, ich schlaf mal drüber und versuch mich dann daran. Wenn's was neues gibt, berichte ich es!
 
Korbinian, das geht wunderbar. Man muss nur das Einmaleins des Dateihandlings beachten, von wegen flock & Co.
Für wenige Benutzer mit moderat vielen Beiträgen mag' das noch wunderbar funktionieren, aber wenn das mal mehr und mehr werden, würde ich erwarten, dass das extrem langsam wird.

Am allerbesten wäre, dem Rat mit der Datenbank zu folgen, da geht sowas nämlich etwas einfacher.
Genau deswegen sagte ich ja auch
...;)

@Julian: ich würde dann auch nur die neuen Nachrichten ausliefern, wenn es neue gibt, und nicht komplett alles noch einmal neu rausgeben. Ein += an das .innerHTML ist dann auch nicht mehr so ideal. Besser wäre es, wenn du dann für jede Nachricht per document.createElement(); ein <div> erzeugst, dem du dann den Inhalt der Nachricht zuweist (ACHTUNG: du musst auch noch sicher stellen, dass die Nachricht kein HTML enthält, dass irgendwas böses anstellen könnte) und dann an's Ende deiner Darstellen packst.
 
Zuletzt bearbeitet von einem Moderator:
Zurück
Oben