Web/DB プログラミング徹底解説

ホーム > JavaScript プログラミング > DOM イベント処理 (2) mousemove ~ Ajax による改良

DOM イベント処理 (2) mousemove ~ Ajax による改良

はじめに

この資料では前回の資料  "DOM イベント処理 (2)" で作ったコードを改良します。前回の記事を FTP にアップロードして自宅以外の(特に回線の細い)環境から見てみると、画像のロード時間が無視できないことに気づきました。このため、この画像のロードを 非同期で行い、画像のロード中は "Loading..." のメッセージを表示し、ロードが終了したらメッセージを消します。

出来上がりは次のようになります。

Loading...

さっそく解説に入ります。

1. 考え方

いまどきのメジャーなブラウザはそのままでも、もちろん非同期で画像をダウンロードするには違いがないのですが、前回のコードでは小さ な領域にロー ドするわりに画像が巨大(詳細図のため)なため、待たされることに違和感を感じてしまいました。このため、今何をやっているのか、ユーザーに状況をレポー トすることを考えました。すなわち、画像を読み込んでいる最中は "Loading..." というメッセージを表示しておき、画像のロードが終わったらそのメッセージを消します。ちなみに、ここでは画像のロード場所はブラウザのキャッシュに頼っ ています(今のところこれでうまくいくので深入りしないことにします。あしからず)。

さて、非同期読み込みには Ajax の典型的な手法を使っています。例によって、window の load イベントハンドラでスクリプトを初期化していますが、初期化時にいきなり HTTP リクエストを送信します。

function initScript(e) {
    SendRequest( g_sImageURL );
}

addEvent(window, 'load', initScript, false);

ここで g_sImageURL は画像のURLです。 addEvent については以前の資料をご覧ください

SendRequest は次のコードです。

function SendRequest (url, params, method) {
    if (!method) {
        method = "GET";
    }
   
    g_Request = GetXmlHttpRequest();
   
    if ( !g_Request ) {
        return;
    }
   
    g_Request.onreadystatechange = OnReadyState;
    g_Request.open(method, url, true);
    g_Request.send(params);
       
}

g_Request には XmlHttpRequest オブジェクトを保持します。オブジェクトの readyState の変更イベントハンドラとして OnReadyState を指定します。ステートの変更は一般に、LOADING(1)、LOADED(2), INTERACTIVE(3), COMPLETE(4) の順番で変わります。OnReadyStateでステートをチェックして、それが COMPLETE(4) ならばロードが完了したとしています。ちゃんとチェックするならば HTTP ステータスまで見るべきですが、今回は実装していません(手抜きです)。

オブジェクトの取得は次のコードです。

function GetXmlHttpRequest () {

    var req = null;
   
    if ( window.XMLHttpRequest ) {
        req = new XMLHttpRequest();
    }
    else if ( window.ActiveXObject ) {
        req = new ActiveXObject("Msxml2.XMLHTTP");
    }
   
    return req;
}

window.ActiveXObject = true のコードパスは MS-IE 用ですが、こちらは Msxml2.XMLHTTP 一種類にしています。

OnReadyState にて、画像ロードが完了したことを確認したら、"Loading..." というメッセージを示していたテキストノードを削除して完了です。

function OnReadyState(e) {

    if ( g_Request.readyState == READY_STATE_COMPLETE ) {
        var elm = document.getElementById('msg');
        // elm.innerHTML = '';
        elm.parentNode.removeChild(elm);
        startPlaying();
    }
    else {
        // do nothing
    }
}

2. リスト

リスト全体は以下のようになります。前回、前々回の延長でもありますので、適宜補ってください。

//
// 1/10/2006 Keisuke Oyama
//

var g_Request = null;

var READY_STATE_UNINITIALIZED = 0;
var READY_STATE_LOADING       = 1;
var READY_STATE_LOADED        = 2;
var READY_STATE_INTERACTIVE   = 3;
var READY_STATE_COMPLETE      = 4;

var g_sImageURL = './scr09/pic3.jpg';
var isIE = false;


///////////////////////////////////////////////////////////////////////////////


function startPlaying(e) {
    if ( document.getElementById ) {
        var thumbnail = document.getElementById('thumb');
        addEvent(thumbnail, 'mousemove', onMouseMove, false);

        var elmVwr = document.getElementById('viewer');
        elmVwr.style.background = 'url(' + g_sImageURL + ')';
        elmVwr.style.backgroundRepeat = 'no-repeat';
    }
   
    if ( !window.opera && navigator.userAgent.indexOf('MSIE') != -1 ) {
        isIE = true;
    }
}

... 途中省略 ...

///////////////////////////////////////////////////////////////////////////////


function SendRequest (url, params, method) {

    if (!method) {
        method = "GET";
    }
   
    g_Request = GetXmlHttpRequest();
   
    if ( !g_Request ) {
        return;
    }
   
    g_Request.onreadystatechange = OnReadyState;
    g_Request.open(method, url, true);
    g_Request.send(params);
       
}


///////////////////////////////////////////////////////////////////////////////


function GetXmlHttpRequest () {

    var req = null;
   
    if ( window.XMLHttpRequest ) {
        req = new XMLHttpRequest();
    }
    else if ( window.ActiveXObject ) {
        req = new ActiveXObject("Msxml2.XMLHTTP");
    }
   
    return req;
}


///////////////////////////////////////////////////////////////////////////////


function OnReadyState(e) {

    if ( g_Request.readyState == READY_STATE_COMPLETE ) {
        var elm = document.getElementById('msg');
        elm.parentNode.removeChild(elm);
        startPlaying();
    }
    else {
        // do nothing
    }
}


///////////////////////////////////////////////////////////////////////////////


function initScript(e) {

    SendRequest( g_sImageURL );
   
}


///////////////////////////////////////////////////////////////////////////////


addEvent(window, 'load', initScript, false);