Samuel Williams Thursday, 03 June 2010

In a comment form, you might want to send the data using AJAX to get a preview. In this case, you generally want to aggregate the events so that you only fetch a new preview when the user stops typing or a certain timeout is reached.

Here is some JavaScript code for implementing this kind of behaviour.

function AggregateCallback (timeout, enforce, callback) {
	this.timeout = timeout;
	this.enforce = enforce;
	this.callback = callback;
	this.timer = null;
	this.fired = null;
} = function () {
	this.fired = new Date();

AggregateCallback.prototype._expired = function () {
	// Returns true if we have been fired further than maxTimeout in the past.
	return !this.fired || ((new Date() - this.fired) > this.timeout);

AggregateCallback.prototype.update = function () {
	if (this._expired() && this.enforce)
	if (this.timer) {
		this.timer = null;
	var target = this;
	this.timer = setTimeout(function () {; }, this.timeout);

Here is an example of how to use it:

var commentsForm = $(...);

var livePreview = new AggregateCallback(1000, true, function() {
	$.post("comments/preview", {'body': $('textarea[name=body]', commentsForm).val()}, function(data) {
		$('.preview', commentsForm).html(data);
		$.syntax({context: $('.preview', commentsForm)});

$('textarea[name=body]', commentsForm).keyup(function() {

Here is an explanation of how it works: You create an AggregateCallback with a timeout value (in milliseconds). You call update a number of times. If you don't call update within the timeout, the callback is fired.

If you set enforce to true, the callback will be fired every timeout milliseconds, and also finally timeout milliseconds after the last call to update. This means that, in the case of a live preview, the server will be polled once every second even while the user is continuing to type.


Leave a comment

Please note, comments must be formatted using Markdown. Links can be enclosed in angle brackets, e.g. <>.