sistrall.it
Published on May 17, 2005

Ajax enabled comments for Movabletype explained

Hey, this post is vintage content. It dates back more than 19 years ago: it may contain outdated and inaccurate information.

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.

I am Silvano Stralla. I am a developer, I like taking photos and riding bikes.
If you want, you can write to me at silvano.stralla at sistrall.it.
This site is handmade, with love, in Turin (Italy).

© 2002—2024 Silvano Stralla

This page was built on Mon, 15 Jul 2024 14:51:15 GMT from code version a494c001.