いまさら人に聞けないAjaxと簡単なサンプル


入門 Ajax
入門 Ajax
posted with amazlet on 06.04.22
高橋 登史朗
ソフトバンククリエイティブ (2005/11/15)
売り上げランキング: 65,811

Ajax 実装のための基礎テクニック
増井 雄一郎 深津 貴之 川崎 有亮 台場 圭一 WINGSプロジェクト 佐藤 真介
技術評論社 (2006/03/23)

JavaScript & DHTMLクックブック―Webエキスパート必携テクニック集

JavaScript & DHTMLクックブック―Webエキスパート必携テクニック集

Ajaxとは

最近、猫も杓子も「Ajax」というほど、よく目にする「Ajax」という言葉。
実は何なのかよく分かっていないという方もいらっしゃるのではないでしょうか。
かくいう私も人に説明できるほど完璧に理解しているか?と言われると微妙なので、「Ajax」についてまとめてみようと思います。


まずは言葉の定義から。はてなダイアリーキーワードAjax」によると

Asynchronous JavaScript + XMLの略称。

JavaScript の組み込みクラスである XMLHttpRequest を利用した非同期通信を利用して、ウェブブラウザ上で既存の枠組みにとらわれないインタフェースを実現するための技術。実際には Ajax という技術が存在しているわけではなく、DHTML (JavaScript + CSS) と XMLHttpRequest にサーバーサイドのウェブアプリケーションとを加えたあわせ技のことを Ajax と呼ぶようになった。

Ajax を用いて構築されたインタフェースの代表例として Google SuggestGoogle Maps がある。

中略

Ajax の要素には XML も含まれているが、実際には XMLHttpRequest で取得した HTML ソースを innerHTML で流し込むという方法もよく使われるため、必ずしも XML による通信がなければいけないというわけではないようだ。すなわち、XMLHttpRequest における非同期通信機能がその肝である。


だそうです。
大雑把に言うと、「既存のWebっぽくないユーザーインターフェースを、DHTML/XMLHttpRequest(非同期通信機能)を利用して実現するぜ。」という感じでしょうか。
ちなみに「Ajax」は「えいじゃっくす」と発音するのが正しいようです。

簡単なサンプル

はてなのいくつかのシステムではAjaxを使っているのですが、最初のサンプルとしてはちょっと難しいので、簡単なサンプルを作ってみようと思います。
ありえないシチュエーションだったり、エラー処理がなかったりとかなり手抜きですが、あくまでもサンプルということで。
(動作確認はFirefoxで行っています。)


次のような機能を実現してみましょう。
・フォームが1つある。
・フォームにはテキストボックスがひとつあり、そこに文字列を入力して、入力完了後にその値をデータベースに反映したい。


これをAjaxを使用せず実装すると以下のような感じになると思います。

・フォームにテキストボックスとsubmitボタンを配置する。
・ボタンを押すとsubmitされ、テキストボックスの値がPOSTされる。
・画面がリロードされる。


sample.html

<!DOCTYPE HTMLPUBLICWCDTDHTMLTransitionalENhtmlheadmetahttpequiv="Content-Type" content="text/html; charset=utf-8">
<meta httpequiv="Content-Style-Type" content="text/css">
<meta httpequiv="Content-Script-Type" content="text/javascript">
<title>Ajaxを使わないサンプル</title>
</head>
<body>
<form action="noajax.cgi" method="post">
<input type="text" name="text" value="デフォルトの値">
<input type="submit" value="POST">
</form>
</body>
</html>

noajax.cgi

#!/usr/bin/perl
use strict;
use CGI;

main();

sub main {
	my $q = CGI->new();
	my $text = $q->param('text');

        # $textをデータベースに格納

        # 何らかの出力
}


どうでしょうか?これはよく見かける、なじみのある方法だと思います。


次にAjaxを使って同じような機能を実現したいと思います。
Ajaxらしさを出すためにちょっと欲張ってみます。


・画面上テキストラベルに見える部分をマウスクリックすると編集可能になる
・文字列を入力し、Enterキーを押すと、テキストがバックグラウンドで更新され、ラベル表示に戻る。
・画面はリロードされない。


まずは、テキストラベルをクリックすると編集可能になる&入力後Enterキー押下でラベル表示に戻るという部分を作ってみましょう。
ここはかなりインチキ気味です。
もっときれいでスマートな方法がありますがそれはまた今度ということで。


ajax.html

<!DOCTYPE HTMLPUBLICWCDTDHTMLTransitionalENhtmlheadmetahttpequiv="Content-Type" content="text/html; charset=utf-8">
<meta httpequiv="Content-Style-Type" content="text/css">
<meta httpequiv="Content-Script-Type" content="text/javascript">
<script type="text/javascript">

function OnMouseDown() {
    var formtext  = document.getElementById('formtext');
    var divtext = document.getElementById('divtext');
    var textbox = document.getElementById('textbox');

    formtext.style.display = '';    // フォームを表示
    divtext.style.display = 'none'; // ラベルを非表示
    textbox.focus();  // フォーカス
    textbox.select(); // セレクト
}

function Update() {
    var formtext  = document.getElementById('formtext');
    var divtext = document.getElementById('divtext');
    var textbox = document.getElementById('textbox');

    divtext.innerHTML = textbox.value; // 入力された値をラベルに反映

    formtext.style.display = 'none'; // フォームを非表示
    divtext.style.display = '';      // ラベルを表示
}

</script>
<title>Ajaxを使わサンプル</title>
</head>
<body>
<div id="divtext" onmousedown="OnMouseDown();">デフォルトの値</div>
<div id="formtext" style="display:none;">
<form onsubmit="Update();return false;">
<input type="text" name="text" id="textbox" value="デフォルトの値">
</form>
</div>
</body>
</html>

ポイントは3つあります。
・divを2つ用意し、それぞれにラベル・テキストボックスを格納していること。
・マウスイベント・サブミット時に、必ず片方の div が 'display : none'状態に変更され、もう一方が表示状態になっていること。
・divの innerHTMLに値を格納していること。


これでクリックで編集可能になる、ラベル・テキスト部品ができました。


次は、XMLHttpRequestを利用して、入れられた値をサーバー側に POST しましょう。
まずは、XMLHttpRequest用の関数を用意します。
これは今後使いまわすことが可能なので、ajax.jsなどとして外部jsファイルにしておいてもよいかもしれません。

var XMLHTTP_LOAD_COMPLETE = 4;
var XMLHTTP_HTTP_STATUS = 200;
var MSXMLHTTP = false;
var xmlhttp = createXmlHttp();

function createXmlHttp() {
    var xo = false;
    try {
        xo = new ActiveXObject("Msxml2.XMLHTTP");
        MSXMLHTTP = true;
    } catch (e) {
        try {
            xo = new ActiveXObject("Microsoft.XMLHTTP");
            MSXMLHTTP = true;
        } catch (E) {
            xo = false;
        }
    }
    if (!xo && typeof XMLHttpRequest != 'undefined') {
        xo = new XMLHttpRequest();
    }
    return xo;
}


ではUpdate()関数に、肉付けしてPOST処理を書いてしまいます。

function Update() {
    var formtext  = document.getElementById('formtext');
    var divtext = document.getElementById('divtext');
    var textbox = document.getElementById('textbox');

    divtext.innerHTML = textbox.value; // 入力された値をラベルに反映

    formtext.style.display = 'none'; // フォームを非表示
    divtext.style.display = '';      // ラベルを表示

    // POST処理
    var postdata = 'text=' + encodeURIComponent(textbox.value);
    try {
        if (xmlhttp.readyState != 0) xmlhttp.abort();

        xmlhttp.open("POST", './ajax.cgi', true);
        xmlhttp.onreadystatechange = function () {
            if (xmlhttp.readyState == 4 && xmlhttp.responseText) {
                alert(xmlhttp.responseText);
            }
        }
        xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xmlhttp.send(postdata);
    } catch (e){
        alert(e);
    }
}

POSTの方法ですが、これはいつも同じなのでこの形で覚えてしまうのが早いかもしれません。
ここでのポイントは4つあります。
・この方法でPOSTすると画面はリロードされません。
・非同期でPOSTされるので、レスポンスが返ってくるまでの間、何も操作ができないという状態にはなりません。
・レスポンスは、onreadystatechangeハンドラで指定した、functionで受け取ります。
・レスポンスは xmlhttp.responseTextで取得することができます。


このサンプルでは手を抜いて、レスポンスをalertで表示していますが、まじめにやる場合はエラー処理など、いろいろと考えなければいけないと思います。
あとPOST先の ajax.cgiですが、今回のサンプルに関して言えば noajax.cgiとほぼ同じ動きでよいと思います。
これもまじめにやる場合は、POST処理の結果をXMLで返してあげるとAjaxらしいです。


このサンプルを少し応用すると、ワンクリックで編集フォームが表示され、その場で更新できるWikiなどが作れると思います。
(というか実際にありますね。)
さてこの記事の続編はあるのだろうか?

関連記事

id:higepon:20050601:1117597545