Sign in to follow this  
markr

[web] Web Forum - with AJAX!

Recommended Posts

There's been a lot of buzz about this "AJAX" - in fact it's the latest buzzword it seems. So to see what it's all about, I decided to make a little forum to see how it would work. I'd value your opinions about its functionality, whether it works etc. I'm not that intereted in making a fancy design, as you can probably gather from looking at it :) If you manage to break something, please file some kind of bug report, send me a PM or an email. Thanks Mark PS: This is hosted on my home machine, so it may be down. This is not a permanent installation.

Share this post


Link to post
Share on other sites
Just browsing it casually, I have a few comments:

You aren't resetting the page number, so it's possible to see page 3 of 1.

And more importantly, I think it's a mistake to use "AJAX" for navigation. I've worked a lot on creating more dynamic forums, and here are some things I found useful to do:

* Within a thread, allow the user to "quick load" the contents of other pages in the thread. As an added bonus, you could prefetch the next page of the thread to make for insanely fast browsing. (Some people will want to turn this off.)

* Notify the user if someone else has posted while he was writing his post and give him the option to read the new posts or to continue on with submitting his post. (I've found that automatically inserting new posts makes for a weird experience.)

* Display PM notifications "real time"

* Auto-refreshing of Forum Lists / Recent Posts pages

* Previewing / Spellchecking

* Quick bookmarking

* Inline admin tools for deleting posts, etc.

As a general rule, logical pages should be kept as distinct entities. When I want to go from a list of forums to the forum itself, a new page should load. I want to be able to hit my back button on my mouse.

I did some stuff where after making a post, it would submit it away to the server and use JS to add it locally. However, all of that became a major headache to maintain. For instance, if someone else posted in between posts, that had to be added first. And then, if that made the posts past the number of posts allowed per page, a new page had to be added.

All-in-all, while it can be fun to mess with, I'd keep DHTML stuff to things that are nice add-ons, but not crucial to navigation.

Share this post


Link to post
Share on other sites
Quote:
Original post by konForce
You aren't resetting the page number, so it's possible to see page 3 of 1.


Err, yes. This is a known bug. It's easily fixed I think.

Quote:

And more importantly, I think it's a mistake to use "AJAX" for navigation.


I'm not totally convinced myself. It's an experiment.

Quote:

* Within a thread, allow the user to "quick load" the contents of other pages in the thread. As an added bonus, you could prefetch the next page of the thread to make for insanely fast browsing. (Some people will want to turn this off.)


It's an optimisation; I might consider it.

Quote:

* Notify the user if someone else has posted while he was writing his post and give him the option to read the new posts or to continue on with submitting his post.


That's a really good idea. In fact, it could be done on a conventional web forum.

Quote:

* Display PM notifications "real time"


Seeing as current browsers do not support any easy way of doing "server push", nor is doing so particularly efficient on the server-side, it's tricky.

Mozilla supports multipart/replace XMLHttpRequest or something, which can be used for server push. It's still a bit tricky.

Quote:

* Auto-refreshing of Forum Lists / Recent Posts pages


Anything can be refreshed as the client-side decides. Currently the forum list is never refreshed except on logon / logoff - which is probably not often enough. I don't want the user to be tempted to press their browser's "reload" button because it will reload loads of stuff unncessarily (such as the HTML, JS etc)

Quote:

* Previewing / Spellchecking


Gamedev.net has a preview facility. It's not clear whether it sends the message back to the server.

The server-roundtrip preview is quite useful. I may do that. This is because in my current design, the HTML encoding for the post body is done server-side.

Quote:

* Quick bookmarking
* Inline admin tools for deleting posts, etc.


Optional features :)

Quote:

As a general rule, logical pages should be kept as distinct entities. When I want to go from a list of forums to the forum itself, a new page should load. I want to be able to hit my back button on my mouse.


It is true that the conventional browser "back / forward" don't work too well with ajax apps. There are hacks to get around it, but they are ugly.

Quote:

I did some stuff where after making a post, it would submit it away to the server and use JS to add it locally. However, all of that became a major headache to maintain. For instance, if someone else posted in between posts, that had to be added first. And then, if that made the posts past the number of posts allowed per page, a new page had to be added.


That's not how mine works, so it's not difficult.

Mine doesn't add the post locally, it does a round trip to get the messages including the one it's just added.

Quote:

All-in-all, while it can be fun to mess with, I'd keep DHTML stuff to things that are nice add-ons, but not crucial to navigation.


That's not what I'm doing! Thanks for your advice.

Mark

Share this post


Link to post
Share on other sites
Quote:
Seeing as current browsers do not support any easy way of doing "server push", nor is doing so particularly efficient on the server-side, it's tricky.

The way I implemented it was by simply pinging the server every 30 seconds (for a maximum of X amount of times). Not only did I return PM notification, but was able to return various status update things.

On a large site it might introduce a lot of unwanted traffic, but properly optimized, it shouldn't be an issue.

Quote:
Gamedev.net has a preview facility. It's not clear whether it sends the message back to the server.

I believe they use an ugly "post to iframe" to do this (apologies if I'm wrong), when you could do this via XMLHttpRequest across FF, Opera, IE, and Safari.

Using my RPC() class (a wrapper for XMLHttpRequest), I would do:

var rpc = new RPC();
rpc.addField('post', document.getElementById('post'));
rpc.onLoad = function(html)
{
document.getElementById("preview").innerHTML = html;
}
rpc.post("/rpc/preview-message.rpc");




Quote:
That's not what I'm doing!

I assume that is in response to the idea of increasing the functionality of a "traditional" web messaging system.

I don't doubt that one could make a super AJAX web messaging system, but I just don't think it's worth the overall effort. For instance, I want to be able to bookmark pages with my browser, press F5 to refresh, use my mouse's back and forward buttons along with gestures, middle click to open in new tab, and all of that stuff. I would be seriously annoyed at using an AJAX forum that didn't let me do that.

I'm not sure your motives behind doing this, other than to have some fun and try out new ways of doing things. That's all good stuff; I spend a lot of time working on that sort of thing. I actually worked on (for fun) a heavy XMLHttpRequest based forum system like you are doing. But if you are looking for a practical replacement of traditional style of web forums, I don't think a pure AJAX application is going to work unless a lot of time is put into it.

Share this post


Link to post
Share on other sites
Quote:
Original post by konForce

Quote:
Gamedev.net has a preview facility. It's not clear whether it sends the message back to the server.

I believe they use an ugly "post to iframe" to do this (apologies if I'm wrong), when you could do this via XMLHttpRequest across FF, Opera, IE, and Safari.



The post preview uses "AJAX". And I definitely agree that pages should be separated into logical units for navigation purposes. Hitting the back button by accident is a nightmare if all navigation is controlled through the application itself.


<SCRIPT language="JavaScript">
<!--
function ConfirmPost(authorName)
{

if (document.PostTopic.UserName.value.toUpperCase() != authorName.toUpperCase() && authorName != "")
{
var edit= confirm("You are attempting to edit someone else's post. Are you sure you wish to proceed?");
if (edit==true)
{
document.PostTopic.submit();
}
}
else
{
document.PostTopic.submit();
}
}

var previewActive = false;
var edited = false;
var preview_content = "";

function writeLayer(layerID,txt){
if(document.getElementById){
document.getElementById(layerID).innerHTML=txt;
//alert( txt );
}else if(document.all){
document.all[layerID].innerHTML=txt;
}else if(document.layers){
with(document.layers[layerID].document){
open();
write(txt);
close();
}
}
}

function showLayer(layerID){

if(document.layers){
document.layers[layerID].visibility = "show";
}
else if(document.getElementById){
document.getElementById(layerID).style.visibility = "visible";
}else if(document.all){
document.all[layerID].style.visibility = "visible";
}
}

function hideLayer(layerID){

if(document.getElementById){
document.getElementById(layerID).style.visibility = "hidden";
}else if(document.all){
document.all[layerID].style.visibility = "hidden";
}else if(document.layers){
document.layers[layerID].visibility = "hide";
}
}

function processReqChange() {
// only if req shows "loaded"
if (req.readyState == 4) {
// only if "OK"
if (req.status == 200) {
writeLayer("previewLayer", "<div class=\"forumcell\" style=\"width: 670px; height: 325px;\"><div class=\"preview\">" + req.responseText + "<&#47;div><&#47;div>");
preview_content = req.responseText;
} else {
alert("There was a problem retrieving the XML data:\n" +
req.statusText);
}
}
}

function submitform ()
{
var strResult, isIE;


if (edited)
{
writeLayer("previewLayer", "<table width=670><tr height=300 valign=middle><td align=center class=mediumfont>Please wait.. generating preview<&#47;td><&#47;tr><&#47;table>");

if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = processReqChange;
req.open("POST", "postpreview.asp", true);
req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
req.send("msg=" + escape(document.PostTopic.message.value));

// branch for IE/Windows ActiveX version
} else if (window.ActiveXObject) {
isIE = true;
req = new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange = processReqChange;
req.open("POST", "postpreview.asp", true);
req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
req.send("msg=" + escape(document.PostTopic.message.value));

}
}
}
else
{
writeLayer("previewLayer", "<div class=\"forumcell\" style=\"width: 670px; height: 325px;\"><div class=\"preview\">" + preview_content + "<&#47;div><&#47;div>");
}

edited = false;
}

function togglePreview ()
{
if (previewActive)
{
hideLayer("previewLayer");
showLayer("postLayer");
previewActive = false;
writeLayer("prevLink", "<a href=\"javascript:;\" onclick=\"togglePreview()\">Show Preview<&#47;a>");
document.PostTopic.message.focus();
document.PostTopic.message.style.cursor = 'text';
writeLayer("previewLayer", '<style type=\"text&#47;css\"> <!-- .preview {border: solid black 2px; width: 670px; height: 325px; padding: 1px; } --> </style>');
}
else
{
hideLayer("postLayer");
showLayer("previewLayer");
writeLayer("prevLink", "<a href=\"javascript:;\" onclick=\"togglePreview()\">Hide Preview<&#47;a>");
submitform ();
previewActive = true;
}
}

//-->
</SCRIPT>



---
Michael Tanczos

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this