Catalystでajax - 補足

今回はCatalystはあんまり関係なくて、prototype.jsの使い方に関する補足、といった感じです。

前回のエントリの最後で、「xmlHttpRequestで取得したデータを、単純にそのままHTMLにはめ込むだけなので、サーバ側で生成したデータを、Javascript側で何らかの処理をしてからHTMLにはめ込むという用途には使えませんが、単純なajaxアプリであれば十分使えるかと。」ということを書いたのですが、これはHTML::Prototypeが吐き出すJavascriptが、基本的にAjax.Updaterという関数を使っているからですね。なので、prototype.js自体が、「Javascript側で何らかの処理をしてからHTMLにはめ込む」という処理ができない、というわけではないです。

この様な処理をするには、具体的には以下の様なコードになります。ただしこの方法では、HTML::PrototypeやCatalyst::Plugin::Prototypeが使えないので、若干手間が増えます。

<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript">
function completed(request){
    var data = request.responseText;
    // 何か処理をする...
}
</script>
<form onsubmit="new Ajax.Request( '/url', { parameters: Form.serialize(this),onComplete: function(request){ completed(request) } } ) ; return false;">
<input type="text" name="text" />
<input type="submit" />
</form>

肝になるのはAjax.Requestという関数を使っていることと、「onComplete」の部分ですね。この部分で、xmlHttpRequestでサーバからデータを取得完了した時点で実行する関数を指定できます。requestはxmlHttpRequestオブジェクトなので、呼び出した関数内で、request.responseTextでサーバからのデータを取り出すことができます。その上で取得したデータに対して何か処理してやれば良い、ってわけですね。

HTML::PrototypeやCatalyst::Plugin::Prototypeが使えないのはちょっと痛いですが、Ajax.Request関数の書式に慣れてしまえば、自分でxmlHttpRequest周りのコードを書かなくて良いのですから、メリットの方が大きいと思います。

で、実際に上の方法を用いて、ajaxでdel.icio.usを使いやすく #0のdel.icio.usサイドバーのJavascript部分を書き直してみると、どんな感じになるのか見てみることにします。

まず、prototype.jsを使わずに何も考えずに書いたもの。(xmlHttpRequestを使っているfunctionのみ抜き出しています。)JSON形式のデータを受け取って、evalでオブジェクトに変換する、という処理です。

function init() {
    tagsArea.innerHTML = '<p class="loading">loading tags ...</p>';
    
    var req1 = new XMLHttpRequest();
    if(req1){
    req1.onreadystatechange = function() { 
        if (req1.readyState == 4 && req1.status == 200) {
        eval('tagsListObj = ' +  req1.responseText);
        displayTags();
        }
    };
    req1.open('GET', '/delside/index.cgi');
    req1.send(null);
    }

    var req2 = new XMLHttpRequest();
    if(req2){
    req2.onreadystatechange = function() { 
        if (req2.readyState == 4 && req2.status == 200) {
        eval('tagToLinkObj = ' +  req2.responseText);
        }
    };
    req2.open('GET', '/delside/index.cgi?rm=tagToLink');
    req2.send(null);
    }
    
}

次にprototype.jsのAjax.Request関数を使って書き直したもの。

function init() {
    tagsArea.innerHTML = '<p class="loading">loading tags ...</p>';
    
    new Ajax.Request( '/deislde/index.cgi',
    {
    method: 'GET',
    onComplete: function(request){
        eval('tagsListObj = ' +  request.responseText);
        displayTags();
    }
    });
    
    new Ajax.Request( '/delside/index.cgi?rm=tagToLink',
    {
    method: 'GET',
    onComplete: function(request){
        eval('tagToLinkObj = ' +  request.responseText);
    }
    });
    
}

太字部分が変更された箇所です。若干ですが、コードがすっきりしましたよね?

以上、prototype.jsがこんな風にも使える、という例でした。おしまい。