AjaxでRubyのクラス(の名前だけ)をインクリメンタル検索

Ajaxが流行りのようなので、Web上から情報を集めてJavascript + XMLHttpRequestを使ったAjaxアプリケーションを試作してみた。題材はお決まりのインクリメンタル検索。Rubyのクラスの一覧を検索するもの。IEFirefoxなら動くはず。

構成はCGIとDHTML(Javascript)の二本だて。CGIはクエリ(文字列)を与えられると、そのクエリ文字列を名前に含むクラス一覧を動的に生成して返す。Rubyで実装してある。DHTMLはそのドライバで、onkeyupを補足してテキストフィールドに入力された文字をクエリとして発行し、結果を表示する。なんて素朴なサンプルだ。

CGIファイルをtest.cgiという名前にして、htmlと同じところに置けば動作するはず。CGIのファイル名/置き場所を変えたいときは、Javascriptの先頭のsearchurlという変数にCGIのURLをセットすればOK。

今回は、改行区切りのplaintextを送受信しているけど、ここをJSONにするのも簡単だろう。operaで動かしたかったら、IFRAMEをXMLHttpRequestの代りに使う手法がある*1。だいたいこういう作りでAjaxエンジンができそうだ。簡単でいいね。

あれ、そういえば、クライアントとサーバーでコネクションを保持したまま双方向的にやりとりする、なんつーのはできるのかな。やりたい。調べないと。

以下ソース。
CGI側。
エラーとかセキュリティまわり何も考えてないので、危険かも。自己責任で。

#!/usr/bin/env ruby
require 'cgi'
cgi = CGI.new
print cgi.header({"type"=>"text/plain","charset"=>"euc-jp"})
key = cgi.params['key'] || ''
list = []
ObjectSpace.each_object(Class) do |klass|
  list << klass.to_s if klass.to_s =~ /#{key}/
end
puts list.sort.join("\n")
puts

DHTML側。
例によって、はてなエスケープモジュールがHTML内のコメントタグを解釈してくれやがって、スクリプト部分が全て消しとんでしまったのでコメントタグをはずしてある。必要なら、スクリプトのまわりに入れてください。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>AJAX テストページ</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-jp">
<script language="JavaScript">


var searchurl = "test.cgi"
function get_data(url,f){

    function make_xml_http(){
	var xmlhttp=false;
	try {
	    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
	} catch (e) {
	    try {
		xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
	    } catch (E) {
		xmlhttp = false;
	    }
	}
	
	if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
	    xmlhttp = new XMLHttpRequest();
	}
	return xmlhttp;
    }
    
    var xmlhttp = make_xml_http();
    xmlhttp.open("GET",url,true);
    xmlhttp.onreadystatechange= function() {
	if (xmlhttp.readyState==4) {
	    f(xmlhttp.responseText);
	}
    }
    xmlhttp.send(null);
}


function search(key){
    function printbyid(id,data) {
	var div = document.getElementById(id);
	div.innerHTML = data;
    }

    printbyid('label',key);
    
    var callback = function(data){
	var ar = data.split("\n");
	dis = ar.join("<br/>");
	printbyid('output',dis);
	printbyid('wait','');
    }
    var url = searchurl + "?key="+key;
    get_data(url,callback);
    printbyid('wait','searching...');
}

function keyup(){
    var key = document.getElementById('input').value;
    search(key);
}


</script>
</head>
<body onload='search("");'>
<h2>Rubyのクラス インクリメンタル検索 (Firefox か IEで動作するはず)</h2>
<input id='input' type="text" onkeyup='keyup();'></input> <span id='wait'></span>
<br/>
Rubyクラスから"<span id='label'></span>"を検索しました

<hr/>
<div id='output'></div>
</body>
</html>