ショッパーズ

Ajax 基礎

InfoTech

Ajax 基礎


「Ajax」とは何か?

「Ajax」はAsynchronous JavaScript + XMLの略称であり「エイジャックス」と読む。間違っても「アジャックス」とか人前で言っては なりません。「エージェーエーエックス」等とのたまうのは、もってのほかです。
ちなみに 「Ajax」という言語や開発環境は存在せず、JavaScript の組み込みクラスである XMLHttpRequest を利用した非同期通信を利用して、ウェブブラウザ上で非同期的なインタフェースを実現することを総称して「Ajax」と呼んでいます。
なお、本企画ではJavaScriptと何らかのサーバサイド言語を大まかに理解しているかたを想定して書いています。ご了承ください。

とりあえず、やってみる?

著者の所属するミラクル産業では、古き時代よりプログラム言語を習得する際には、先ず「足しザウルス」を作るところから始めるという習しがあります。今回もそれに従って「足しザウルス 」を作ることから始めます。「足しザウルス」が何かご存知で無い方に説明しますと、「足しザウルス」とは「ユーザーから2回の数値入力を受け付け、その2つの数値を加算してユーザーに返す」という処理を行うプログラムの総称であります。

とりあえず、作成したのがコレです。

足しザウルス for Ajax

+ =

数値を入力して「計算」ボタンを押してみてください。

JavaScriptだけでも十分に処理可能なプログラムですが、サーバーに足し算のリクエストを出して計算結果を受け取って表示するという、非常に無駄なシステムとなっています。操作していただけると判りますが、サーバとの通信を行ってもペー ジのリロードが行われていないというのがAjaxの特徴です。

クライアント側(ブラウザ)の処理は?

Ajaxの構造上、サーバ側よりもブラウザ側(JavaScript)のコーディングの方が煩雑になります。

[ajax_01.js]
001 function HttpResponse() {
002 
003     if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
004         var xmlDoc = xmlHttp.responseXML;
005 
006         if (xmlDoc.documentElement) {
007             var z = xmlDoc.getElementsByTagName('z').item(0).firstChild;
008         } else {
009             var z = 0;
010         }
011 
012         document.getElementById('z').value = z.data ;
013 
014     }
015 }
016 
017 function HttpRequest() {
018 
019     var x = document.getElementById('x').value;
020     var y = document.getElementById('y').value;
021 
022     xmlHttp.open('GET', 'http://shoppers-jp.com/tech/ajax_01.cgi?x=' + x + '&y=' + y , true);
023     xmlHttp.onreadystatechange = HttpResponse;
024     xmlHttp.send(null);
025 
026 }
027 
028 function getXmlHttpObject() {
029     var xmlhttp;
030     /*@cc_on
031     @if (@_jscript_version >= 5)
032         try {
033             xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
034         } catch (e) {
035             try {
036                 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
037             } catch (E) {
038                 xmlhttp = false;
039             }
040         }
041     @else
042         xmlhttp = false;
043     @end @*/
044     if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
045         try {
046             xmlhttp = new XMLHttpRequest();
047             xmlhttp.overrideMimeType("text/xml"); 
048         } catch (e) {
049             xmlhttp = false;
050         }
051     }
052     return xmlhttp;
053 }
054 
055 var xmlHttp = getXmlHttpObject();
056 

HttpRequestファンクションでは、formのデータを読み込み、XmlHttpを利用してサーバプログラム ajax_01.cgi を起動します。

23行目で、通信ステータスが変更された時の呼び出しファンクション(HttpResponse)を指定しています。

getXmlHttpObjectファンクションの「/*cc_on」で始まっているコメント部分は必要ですので削除しないようにしてください。オブジェクトの生成方法のブラウザ毎の差異を吸収するために、このような書き方になっています。あんまり悩まずに呪文として覚えておいてください。

HttpResponseファンクションは、通信が完了したことを確認して、受信したXMLから必要な要素を取り出し、テキストボックスに入れます。

[参考] readyStateの値について。
0
(UNINITIALIZED)
オブジェクトは、作成されていますが、まだ、初期化されていません
(open メソッドは呼ばれていません)。
1
(LOADING)
オブジェクトが作成されましたが、まだ、send メソッドは呼ばれていません。
2
(LOADED)
send メソッドは呼ばれましたが、statusとヘッダはまだ届いていません。
3
(INTERACTIVE)
いくつかのデータを受け取りました。この状態ではresponseBodyやresponseTextプロパティはエラーを返すでしょう。それは、statusとレスポンスヘッダがまだすべて届いていないからです。
4
(COMPLETED)
すべてのデータを受け取りました。responseBody と responseText プロパティの完全なデータが利用可能です。

 
[ajax_01.html(より抜粋)]
001 <form action="post">
002 <p>足しザウルス for Ajax<br>
003 <center>
004 <input type="text" size="5" name="x" id="x"> + 
005 <input type="text" size="5" name="y" id="y"> = 
006 <input type="text" size="5" name="z" id="z">
007 <input type="button" value="計算" onClick="HttpRequest()"><br>
008 </center></p>
009 </form>
010 

記述するまでも無いのかも知れませんが、htmlファイルのformの記述は以上のようになっています。
通信が必要なタイミングで「HttpRequest()」を呼び出す書き方をすれば、どのような形でも構いません。

サーバ側はどうなってるの?

基本的にクライアントから投げられたパラメータをもとに処理(DBアクセス等)を行い、結果を適当にXML形式で返してあげます。
試しに、http://shoppers-jp.com/tech/ajax_01.cgi?x=10&y=20 をクリックしてみてください。「<z>30</z>」との記述のXMLが返ってきます。
勘の良い方なら全てが判ったと思いますが、このようにサーバが返したXMLを先ほどのJavaScriptの7行目の「xmlDoc.getElementsByTagName('z').item(0).firstChild」で必要な部分を拾い出して使用するという仕掛けです。Ajaxと言っても、基本は単純ですXMLなので返すパラメータを複数にすることも簡単ですね?
 

[ajax_01.html(より抜粋)]
001 #!/usr/bin/perl
002 
003 # Ajax サンプル1
004 
005     get_form();
006 
007     my $x = $FORM{'x'};
008     my $y = $FORM{'y'};
009     
010     my $z = $x + $y;
011     
012     print "Content-Type: text/xml\n\n";
013     print '<?xml version="1.0" standalone="yes"?><tashi><z>' . $z . '</z></tashi>';
014 
015 sub get_form {
016     read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'}); # POST
017     $buffer .= $ENV{'QUERY_STRING'};            # GET
018     
019     @pairs = split(/&/,$buffer);
020     foreach $pair (@pairs){
021         ($name,$value) = split(/=/,$pair);
022         $value =~ tr/+/ /;
023         $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("H2",$1)/eg;
024         $value =~ s/\x0D\x0A/\r/g;
025         $FORM{$name} = $value;
026     }
027 }
028 

クライアント側に合わせて、適当にXMLを作成して送ることができれば、どのように記述しても構いません。

シェルスクリプト
ajax基礎
技術リンク集 2005年版
技術リンク集 2006年版
技術リンク集 2007年版
技術リンク集 2008年版
技術リンク集 2009年版
技術リンク集 2010年版
[STL] ifstreamの使用方法
[STL] CSVファイルの内容をVector配列に取り込む
[STL] テキストファイルを全て読み込む
[WTL] WTLメモ