今回は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がこんな風にも使える、という例でした。おしまい。