Ajax enabled comments for Movabletype explained

Some days ago, I posted about realizing Ajax enabled comments in Movabletype. Here is how.

Why Ajax comments

When you comment a post on a blog, the page that contains the form you have filled and sent reloads. Instead, using Ajax only part of the page is reloaded.

From the client side, Ajax is substantially a Javascript, more or less complex, that simulates a browser without interface inside the browser you are using. The responses to the requests made by this pseudo-browser are interpreted by the script and translated in live changes to the page you are on.

From the server side, Ajax is… nothing! The pseudo-browser makes standard requests and receives standard responses. You only need to request the right page at the right moment.

But…

My first idea for implementing Ajax on MT was hacking the Perl. The second one was writing a plugin. But reading MT’s code I had a surprise!

From the file Comments.pm of MT library:

# Form a link to the comment
my $comment_link;
if (!$q->param('static')) {
    my $url = $app->base . $app->uri;
    $url .= '?entry_id=' . $q->param('entry_id');
    $url .= '&static=0&arch=1' if ($q->param('arch'));
    $comment_link = $url;
} else {
    my $static = $q->param('static');
    if ($static == 1) {
        # I think what we really want is the individual archive.
        $comment_link = $entry->permalink;

    } else {
        $comment_link = $static . '#' . $comment->id;
    }
}

...

return $app->redirect($comment_link);

That static parameter, which is almost ignored in Movabletype documentation, is the key of everything: if the request includes a parameter named static with value different from 1, the value of that parameter is used like an URL to redirect the user.

The trick is all here. A little bit of Javascript makes the rest.

The client side

The Javascript is composed by 2 fundamental functions.

function initializeAjax() {
  var s = false;
  if (typeof XMLHttpRequest != 'undefined') {
    s = new XMLHttpRequest();
  } 
  else {
    try {
      s = new ActiveXObject("Msxml2.XMLHTTP");
    } 
    catch (e) {
      try {
        s = new ActiveXObject("Microsoft.XMLHTTP");
      } 
      catch (E) {
        s = false;
      }
    }
  }
  
  return s;
}

initializeAjax() is the function that returns the hidden browser, which is a software object on which you can operate using a series of functions.

function sendComment(response_page) {

  connection = initializeAjax();
  if (!connection) { 
    return true; 
  }

  var remember = "";
  var forget = "";
  
  var fields = document.getElementById("comments_form").elements;
  
  fields["post"].setAttribute("disabled", "true");
  fields["post"].setAttribute("value", "Processing...");
  
  var requestText = '';
  requestText += "author="+encodeURIComponent(fields["author"].value);
  requestText += "&entry_id="+encodeURIComponent(fields["entry_id"].value);
  requestText += "&email="+encodeURIComponent(fields["email"].value);
  requestText += "&url="+encodeURIComponent(fields["url"].value);
  requestText += "&text="+encodeURIComponent(fields["text"].value);
  requestText += "&static="+encodeURIComponent(response_page);
  requestText += "&post="+encodeURIComponent('POST');
  if (fields["remember"] && fields["remember"].checked==true) requestText += "&remember="+encodeURIComponent(fields["remember"].value);
  if (fields["forget"] && fields["forget"].checked==true)   requestText += "&forget="+encodeURIComponent(fields["forget"].value);

  connection.open("POST","/cgi-bin/mt/mt-comments.cgi",true);
  connection.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
  connection.setRequestHeader('Content-Length', requestText.length);

  connection.onreadystatechange = function() 
  {
    if (connection.readyState == 4) {
      response = connection.responseText;
      if ( (connection.status == 200 && response != "invalid") && !response.match(/<html>.*<\/html>/) && !response.match(/<meta[^>]*>/)) {
        document.getElementById("comments").innerHTML = response;
      }
      else {
        window.alert("Spiacente, ma non e' possibile processare ora il tuo commento. Prova piu' tardi, per favore...");
        fields["post"].removeAttribute("disabled");
        fields["post"].setAttribute("value", "Post");
      }
    } 
  }


  connection.send(requestText);

  return false;
}

sendComment() is the function that uses the object returned from initializeAjax() to send request to the server. Once the request is sent, the function waits for the response, that, if regular, is used used to modify the page. sendComment() is called when you send the form, using the onsubmit event of the form element.

The requestText += "&static="+encodeURIComponent(response_page); is the trick: when you send the comment, the XMLHttpRequest object – the hidden browser – is redirected to a specific page (the response_page passed to function sendComment()).

What page?

The response_page is a simple page, generated from MT using an individual template. For example, if you have the posts archived by date using <$MTArchiveDate format="%Y/%m/%d"$>/<$MTEntryTitle dirify="1"$>.html in the Archive File Template, you can create the response_page using a second individual archive with something like <$MTArchiveDate format="%Y/%m/%d"$>/<$MTEntryTitle dirify="1"$>.ajax.html. Being of individual type, this template is rebuild every time a comment is posted.

This template generates the content used to substitute the part of the page interested by Ajax: in the case of comments, the
template could generate files containing the HTML code to use with innerHTML property of a div element (this is what is done here on sistrall.it).

And if there’s no Javascript?

If Javascript is not available for any reason, everything works just like Ajax doesn’t exists: the form is sent from the real browser, the static parameter takes the value 1 from an hidden field and MT redirects the user following the standard way.

Conclusions

That’s all: implementing Ajax enabled comments on MT isn’t difficult at all! The technique here explained is one of the simplest, but more can be done generating, for example, response_pages containing a real XML tree, using the content of different nodes to substitute more elements in the page.

Post your comment

You can use Textile





52 comments

Readers left 52 notes on this photograph. Live yours using the form below.

  • sosa on 19/05/2005

    I will be trying this… i’m not an skilled programmer but I will do my best :D

  • asd on 31/05/2005

    I would like to see how it works when I post.

  • Blank on 22/06/2005

    Nice one

  • Stefano on 24/06/2005

    Però.. carino. Molto.

  • Duncan Ponting on 25/06/2005

    Good work, thanks.

  • Adam on 26/06/2005

    Testin’

  • Neod on 12/07/2005

    testing shmesting

  • erg on 09/08/2005

    gerg

  • e on 27/10/2005

    testing

  • Joe Anderson on 27/10/2005

    How do I do this – I don’t understand.

  • jyoseph on 27/10/2005

    Good work, Would you be able to provide an example of your comment form. I’ve seen another comments/ajax solution and each input field needed an assigned class.

    This is pretty awesome though!

  • Milad on 28/10/2005

    Hi, this is very good..

  • foo on 12/12/2005

    resumé

  • foo on 12/12/2005

    If I use a word with a unicode character, like “resumé”, the JavaScript is OK with it, so it looks fine in the Comment Preview.

    But when I submit it to the backend, the ending “e”, which is supposed to have an aigu accent, ends up getting split from a single multibyte unicode char into two separate latin-1 chars.

  • test on 13/01/2006

    this looks good

  • TheBoy on 16/01/2006

    Hi
    good idea

  • Babak on 16/01/2006

    Thank you so much, so useful!

  • Alex Sancho on 17/01/2006

    only to test

  • Jesse on 18/01/2006

    Testing comments

  • test on 20/01/2006

    test

  • Miles Evans on 25/02/2006

    would love to see your comments template snippet as well thanks ;)

  • hmmm on 04/03/2006

    the page is still reloading!

  • ewrew on 10/03/2006

    test

  • lorenzo on 12/04/2006

    testing

  • lorenzo on 12/04/2006

    test

  • lorenzo on 17/04/2006

    testing again

  • saleh on 07/05/2006

    test

  • o on 11/05/2006

    testin

  • yhfgh on 17/05/2006

    yuyyuyjhguy

  • silva on 18/05/2006

    Does it work here? Is there a Demo page? Going to try it here.

  • Pedro on 18/05/2006

    This is a test

  • tom sherman on 08/06/2006

    Test test test. Is this thing on?

  • www on 08/06/2006

    test

  • test on 22/07/2006

    Test

  • test on 29/07/2006

    test

  • uo on 29/07/2006

    yo

  • WaltDe on 01/09/2006

    Keep up the great work on your blog. Best wishes WaltDe

  • Memms on 28/11/2006

    gtre

  • test on 04/12/2006

    test

  • yv0nytMQlltro9cA on 13/12/2006

    sistrall.it ? blog Ajax enabled comments for Movabletype explained

  • yv0nytMQlltro9cA on 13/12/2006

    sistrall.it ? blog Ajax enabled comments for Movabletype explained

  • yv0nytMQlltro9cA on 13/12/2006

    sistrall.it ? blog Ajax enabled comments for Movabletype explained

  • test on 08/01/2007

    test

  • test on 08/01/2007

    test

  • tesst on 17/01/2007

    test

  • fff on 18/01/2007

    tesr

  • melvin on 20/03/2007

    test

  • yo on 26/03/2007

    thank u

  • test on 19/04/2007

    test

  • vbyx ucbzgoj on 15/11/2007

    xdyjvimse vhbpadwq ibueqmtx mciqsy rgnvthe bxqk tjuisn

  • nwqjtz lcbftgper on 15/11/2007

    jntrzhk uqveabjz lvfhbr zxmrakbf rxai ovjrhd ydavnftcl http://www.nsqxh.spaxjflyv.com

  • jald on 30/12/2007

    amdnalks

Published on
17 May 2005
At
17:42
Tagged
software, Article