その3

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

ajax.js

 次に、AJAX方法論の基礎部分を実現するJavaScriptファイルを見てみます。いきなり、全文を掲載。
 羽田野太巳氏の著作「AJAX Webアプリケーションアイデアブック」を最大限に参考していますが、丸コピではなく、趣旨に合う様改変しています。羽田野太巳氏に謝辞の意を表します。

var httpObj = new Array();
var timerId = new Array();

// XMLHttpRequestオブジェクト作成
function makeXMLHttpRequest(name) {
    try {
        abortXMLHttpRequest(name);

        if(window.XMLHttpRequest) {
            // IE以外
            httpObj[name] = new XMLHttpRequest();
        }
        else
        if(window.ActiveXObject) {
            try{
                // 最新IE
                httpObj[name] = new ActiveXObject("Msxml2.XMLHTTP");
            }
            catch(e2) {
                try{
                    // 旧IE
                    httpObj[name] = new ActiveXObject("Microsoft.XMLHTTP");
                }
                catch(e3) {
                    httpObj[name] = false;
                }
            }
        }
        else {
            httpObj[name] = false;
        }
    }
    catch(e1) {
        httpObj[name] = false;
    }

    // encodeURIComponentが使えるかどうか判断
    if(window.encodeURIComponent) {
        ;
    }
    else {
        httpObj[name] = false;
    }
}

// XMLHttpRequestオブジェクトの通信中止
function abortXMLHttpRequest(name) {
    try {
        httpObj[name].abort();
    }
    catch(e) {
        ;
    }
}

// 適格ブラウザ判断
function objValid() {
    makeXMLHttpRequest("dummy");
    return httpObj["dummy"];
}

// リクエスト送信
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);
    }
}

// メッセージ表示
function message(str) {
    document.getElementById('msg').innerHTML = str;
}

// XMLHttpRequestオブジェクト生成に失敗した場合の処理
function httpObjGenerateFail(str) {
    message(str);
    return false;
}

// タイムアウト処理
function timeout(target_url) {
    // タイマーをストップする
    clearInterval(timerId[target_url]);
    // HTTPリクエストを中断する
    abortXMLHttpRequest(target_url);
    // エラー表示
    return httpObjGenerateFail('タイムアウトになりました。(' + target_url + ')');
}

// イベントリスナ追加
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('ご利用のブラウザでは、インタラクティヴ検索をご利用頂けません!');
    }
}

ajax.jsの解説

冒頭部分。
var httpObj = new Array();
var timerId = new Array();

 httpObjは、XMLHttpRequestオブジェクトを格納する変数です。Array()で配列としているのは、Amazon楽天ビッダーズ、ストアミックスごとのリクエストを非同期で動かしたいからです。各ショッピングモールに対し、それぞれ固有のXMLHttpRequestオブジェクトがアクセスします。
 timerIdは、XMLHttpRequestオブジェクトのタイムアウト処理をするために使います。setIntervalファンクションで得られるIDを格納します。これも、ショッピングモールごとに保持して各タイムアウトを非同期に処理します。

XMLHttpRequestオブジェクト作成ファンクション。
function makeXMLHttpRequest(name) {
    try {
        abortXMLHttpRequest(name);

        if(window.XMLHttpRequest) {
            // IE以外
            httpObj[name] = new XMLHttpRequest();
        }
        else
        if(window.ActiveXObject) {
            try{
                // 最新IE
                httpObj[name] = new ActiveXObject("Msxml2.XMLHTTP");
            }
            catch(e2) {
                try{
                    // 旧IE
                    httpObj[name] = new ActiveXObject("Microsoft.XMLHTTP");
                }
                catch(e3) {
                    httpObj[name] = false;
                }
            }
        }
        else {
            httpObj[name] = false;
        }
    }
    catch(e1) {
        httpObj[name] = false;
    }

    // encodeURIComponentが使えるかどうか判断
    if(window.encodeURIComponent) {
        ;
    }
    else {
        httpObj[name] = false;
    }
}

 本来は、ブラウザの判定をしてやるのが筋ですが、ここでは簡略化しています。
 まず、abortXMLHttpRequestファンクション(後述)を呼び出して、当該XMLHttpRequestオブジェクトの通信を中止しておきます。
 次に、XMLHttpRequestが使えるかどうか判断します。これにはFirefoxなどが対応しています。
 ダメだった場合は、続いてActiveXObjectが使えるかどうか判断します。使える場合は、Msxml2.XMLHTTPのインスタンスを作成してみます。Msxml2.XMLHTTPが使えない場合は、Microsoft.XMLHTTPのインスタンスを作成します。
 ActiveXObjectも使えない場合は、残念ながらAJAXの機能を放棄します。このとき、httpObj[name]には、falseを入れておきます。
 最後に、encodeURIComponentが使えるかどうかを判断します。これは、JavaScriptからURLセーフな文字列を作成するために必要なので、これが使えない場合もAJAXの機能を放棄します。

XMLHttpRequestオブジェクトの通信中止ファンクション
function abortXMLHttpRequest(name) {
    try {
        httpObj[name].abort();
    }
    catch(e) {
        ;
    }
}

 指定されたXMLHttpRequestオブジェクトの通信中止を試みます。
 このファンクションが呼び出されたときに、当該XMLHttpRequestオブジェクトが通信中とは限らない上、そもそもインスタンスが存在するかどうかも不確定なので、try〜catchでエラートラップしておきます。

適格ブラウザ判断ファンクション。
function objValid() {
    makeXMLHttpRequest("dummy");
    return httpObj["dummy"];
}

 index.phpの中に登場したファンクションです。
 makeXMLHttpRequestに"dummy"を渡して呼び出し、httpObj["dummy"]を作成します。このhttpObj["dummy"]の値がfalseの場合は、AJAXが使えないことになります。
 そこで、httpObj["dummy"]がfalseでないときは、適格ブラウザだという結果(true扱いとなる)を返します。

 次回は、ajax.jsの続きを解説します。