Ajax でちょっとしたサンプルを作ってみた。2006年05月28日 01時41分04秒

実行画面

ホットスポットをクリックすると、ページのリロードなしにカウントを増やすプログラム。 Perl の CGI として書いてますが、mod_perl の ModPerl::Registry としても問題なく動作します。プログラムを設置するディレクトリにファイルを書き出せる権限がないと、カウント値を書き出すファイルを作れないのでご注意ください。なお、ファイル形式はシグネチャなしの UTF-8 を想定しています。

use strict;

my ($current, $myself) = $0 =~ m!^(.*/)([^/]+)$!;

unless (-e "$0.count"){
	open fout, ">$0.count"	or die "cannot open file (write): $myself.count";
	print fout '1';
	close fout;
}

my %query;
sub decode_url {
	${$_[0]} =~ tr/+/ /;
	${$_[0]} =~ s/%([0-9a-f][0-9a-f])/pack 'H2', $1/ieg;
}
foreach (split /&/, $ENV{'QUERY_STRING'}){
	my ($name, $val) = split /=/;
	&decode_url(\$name);
	&decode_url(\$val);
	$query{$name} = $val;
}

if ($query{'m'} eq 'ajax'){	# XMLHttpRequest からの読み込みへの応答
	open fin, "<$0.count"	or die "cannot open file (read): $myself.count";
	my $counter = <fin>;
	close fin;
	
	# IE で XmlHttp からの読み込みがキャッシュされてしまうために
	# カウンタが更新されない不具合への対策として、
	# HTTP ヘッダにいろいろと記入している。
	print <<ENDLINE;
Pragma: no-cache
Cache-Control: no-cache
Content-type: text/plain; Charset=UTF-8

{
	"counter"	: $counter
}
ENDLINE
	
	$counter++;
	open fout, ">$0.count"	or die "cannot open file (write): $myself.count";
	print fout "$counter";
	close fout;
}

else {				# ページ読み込みへの応答
	print <<ENDLINE;
Content-type: text/html; Charset=UTF-8

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">

<head>
	<meta http-equiv="content-type" content="text/html; charset=UTF-8">
	<meta name="generator" content="$myself">
	<meta http-equiv="content-style-type" content="text/css">
	<meta http-equiv="content-script-type" content="text/javascript">
	<title>テストページ</title>
	<script language="JavaScript" type="text/javascript"><!--
// XMLHttpRequest オブジェクトを取得する
function createHttpRequest()
{
	if (window.XMLHttpRequest){
		return new XMLHttpRequest();
	}
	else if (window.ActiveXObject){	// Microsoft IE 6.0 or older
		try {
			return new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e1) {
			try {
				return new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch (e2) {
				return null;
			}
		}
	}
	else {				// Ajax 未対応の UA
		return null;
	}
}

// XMLHttpRequest によるリクエストを発行し、カウンター値を取得して、
// ページの表示に反映する
function getCount(request){
	request.open("GET", "$myself?m=ajax");
	request.send("");
	if (typeof ScriptEngine == "function"){
		request.onreadystatechange = function (){
			if (request.readyState == 4){
				callback_get_count(request.responseText);
			}
		}
	}
	else {
		request.onload = function (){
			callback_get_count(request.responseText);
		}
	}
}

function callback_get_count(text){
	eval("res = " + text);
	document.getElementById('counter-view').innerHTML = res.counter;
}

// ページ読み込み時にカウンターを更新
var request = createHttpRequest();
getCount(request);
//	--></script>
</head>

<body>

<p>てすと。</p>

<div><!-- カウンターはここに表示される -->
カウンター : <span id="counter-view"></span>
</div>

<!-- クリックするとカウンターが更新されるホットスポット -->
<p><a href="javascript: void(0)" onclick="getCount(request)">くりっく</a></p>

</body>

</html>

ENDLINE
}

なお、Javascript のデバッグは、Firefox と Venkman JavaScript Debugger で行うことができます。デバッグしたい (ブレークポイントを張りたい) コードを関数の中に収めるように記述するのがポイントです。

その他、参考リンクは以下の通り。