その5

実際動いているサイトはこちら

ajax.jsの解説(続き)

 今回は、httpRequestについて解説します。

リクエスト送信ファンクション。
function httpRequest(target_url,post_data,funcitonReference) {

    message("検索中...しばらくお待ちください。");

    makeXMLHttpRequest(target_url);

    if(!httpObj[target_url]) {
        // HTTPオブジェクト使用不能
        httpObjGenerateFail('ご利用のブラウザでは、インタラクティヴ検索をご利用頂けません!');
    }
    else {
        // タイマーセット
        if(timerId[target_url]) {
            clearInterval(timerId[target_url]);
        }
        timerId[target_url] = setTimeout('timeout("' + target_url + '")',30000);

        // オープン
        httpObj[target_url].open("POST",target_url,true);

        // ステータスチェンジイベントのハンドリング
        httpObj[target_url].onreadystatechange = function() {
            try {
                if(httpObj[target_url].readyState==4) {
                    clearInterval(timerId[target_url]);
                    if(httpObj[target_url].status==200) {
                        funcitonReference(httpObj[target_url].responseXML);
                        message("");
                    }
                    else {
                        return httpObjGenerateFail(httpObj[target_url].status + ' : ' + httpObj[target_url].statusText);
                    }
                }
            }
            catch(e) {
                return httpObjGenerateFail(e.toString());
            }
        }

        // リクエスト送信
        httpObj[target_url].setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        httpObj[target_url].send(post_data);
    }
}

 まず、このファンクションのパラメータについて解説します。
 「target_url」には、リクエスト先のURLが入ります。
 「post_data」には、リクエストの際、POSTパラメータとして渡す文字列が入ります。「xx=aa&yy=bb...」というアレです。
 「funcitonReference」には、「target_url」へのリクエストに対するレスポンスデータ=XMLを処理するためのファンクションへのハンドラが入ります。
 では、本体について解説です。

    message("検索中...しばらくお待ちください。");

 これについては、解説するまでもないです。
 続いては、こちら。

    makeXMLHttpRequest(target_url);

 前回解説したmakeXMLHttpRequestファンクションを呼び出し、httpObj[target_url]のインスタンスを作成します。target_urlのキー値を持ったhttpObjが作成されるわけです。
 このhttpObjを使い、次の判定が行われます。

    if(!httpObj[target_url]) {
        // HTTPオブジェクト使用不能
        httpObjGenerateFail('ご利用のブラウザでは、インタラクティヴ検索をご利用頂けません!');
    }

 ブラウザが適格がどうかを判断します。適格でない場合は、そこで処理を終了します。
 ブラウザが適格だった場合は、その下のブロックが処理されます。

    else {
        // タイマーセット
        if(timerId[target_url]) {
            clearInterval(timerId[target_url]);
        }
        timerId[target_url] = setTimeout('timeout("' + target_url + '")',30000);

          :
        (中略)
          :

        // リクエスト送信
        httpObj[target_url].setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        httpObj[target_url].send(post_data);
    }

 このブロックは、以下のように構成されます。

        // タイマーセット
        if(timerId[target_url]) {
            clearInterval(timerId[target_url]);
        }
        timerId[target_url] = setTimeout('timeout("' + target_url + '")',30000);

 ここではタイムアウトを実装しています。
 まず、target_urlをキー値に持つtimerIdがあるかどうか調べ、あった場合はclearIntervalで、timerIdが行っているだろうと思われるインターバル処理をストップします。
 続いて、そのtimerIdに対し、新たにインターバル処理をさせるようタイマを作成します。setTimeoutの第一パラメータは、ファンクションへのハンドラではなく、実行文字列であることに注意しなければなりません。ここでは、タイムアウト値を30秒(30,000ms)に設定しています。

        // オープン
        httpObj[target_url].open("POST",target_url,true);

 ここでは、当該httpObjのインスタンスの、openメソッドを実行しています。POSTメソッドでのリクエストを行う通信を開始します。

        // ステータスチェンジイベントのハンドリング
        httpObj[target_url].onreadystatechange = function() {
            try {
                if(httpObj[target_url].readyState==4) {
                    clearInterval(timerId[target_url]);
                    if(httpObj[target_url].status==200) {
                        funcitonReference(httpObj[target_url].responseXML);
                        message("");
                    }
                    else {
                        return httpObjGenerateFail(httpObj[target_url].status + ' : ' + httpObj[target_url].statusText);
                    }
                }
            }
            catch(e) {
                return httpObjGenerateFail(e.toString());
            }
        }

 JavaScriptでは、ファンクションをオブジェクトとして保持します。したがって、このような無名ファンクションを作成することが出来ます。
 ここでは、当該httpObjのインスタンスの、onreadystatechangeイベントの発生に際して呼び出されるイベントハンドラを宣言しています。したがって、この処理はonreadystatechangeイベントの発生時に呼び出されることになります。
 readyStateが4になると、通信が一通り完了したことになります。また、そのときstatusが200ならば、サーバーからのレスポンスは正常だったことになります。したがって、その時のみfuncitonReferenceを呼び出すことにします。
 なお、readyStateが4の時は、clearIntervalでタイムアウト処理を切っておきます。

        // リクエスト送信
        httpObj[target_url].setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        httpObj[target_url].send(post_data);

 当該httpObjのsetRequestHeaderメソッドで、コンテントタイプがフォームからの送信をシミュレートしたものであることを示し、sendメソッドで実際のパラメータを送信します。
 その後、onreadystatechangeイベントが起こるまで、当該httpObjは待機した状態になり、通信が完了するなどしてonreadystatechangeイベントが起こったら、先程の無名ファンクション=イベントハンドラが呼び出されます。

 ajax.jsでは、最後に、HTTPリクエストそのものとは関係ないですが、共通として使用するイベントリスナ追加のファンクションを定義しています。

イベントリスナ追加ファンクション。
function addListener(elem,eventType,func,cap) {
    if(elem.addEventListener) {
        elem.addEventListener(eventType, func, cap);
    }
    else
    if(elem.attachEvent) {
        elem.attachEvent('on' + eventType, func);
    }
    else {
        return httpObjGenerateFail('ご利用のブラウザでは、インタラクティヴ検索をご利用頂けません!');
    }
}

 elemには、HTMLエレメント(例外はあるが、平たく言えばタグ)が渡ってきます。
 eventTypeには、「click」「load」などイベントの種別をあらわす文字列が入ります。
 funcには、イベントハンドラとして使用したいファンクションへのハンドラが入ります。
 capには、キャプチャを行うか否かがbooleanで入ります。
 ブラウザによって、「addEventListener」や、「attachEvent」といった違う方法を試みなければならないので、このような分岐になっています。

 次回は、より具体的な処理を行う、plaza.jsについて解説します。