どうやって動いてるの?

ガヴィ・ナラ (2004年12月25日)

コンセプト

テキストボックスにタイプした分だけ、イベントがJavascriptによって発生します。そして、そのイベントごとにHTTP GET リクエストがASPXページに行きます。ASPXページから生成されたレスポンスは、シンプルにテキストボックスの下のdivタグの中に 表示されます。ページはリフレッシュもしくはリロードすること無しに、一つ一つのキーストロークをJavascriptが処理していく わけです。Javascript内で使われているXMLHttpRequestオブジェクトについては アップルのデベロッパーサイトで読むことができます。 このオブジェクトはIE 5.0, Mozilla 1.0, それとアップルのSafari 1.2以上のバージョンでサポートされています。


データベース

データベースにはテーブルが一つ入ってるだけです。各辞書のデータはウェブ上で無料で利用できる物(例えば、パブリック・ドメインと なっている英英辞書は"1913 US Webster's Unabridged"や、"The Project Gutenberg Etext of Webster's Unabridged Dictionary"をベースにした物)です。ダウンロードはここから。 このテーブルの名前はWordListです。

WordList
Word varchar(255)
Type varchar (10)
Meaning text

"Word"をインデックスカラムとして、スピードアップするために作りました。全部で182696語データベースに収録されています。

ASP.NET page

ASP.NET ページは非常に素直に作ってあります。データベースが吐き出す最初の10項目を表示するだけ。 下のコードを見てみて下さい。(これ、本当はSqlDataReader クラスのほうがいいかも知れませんが)


<%@Page Language="C#"%>
<%@Import Namespace="System.Data"%>
<%@Import Namespace="System.Data.SqlClient"%>
<%@Import Namespace="System.Configuration"%>

<script runat="server">

    public void Page_Load(object sender,EventArgs args)
    {
        string keyword=Request["k"];
        if(keyword!=null && keyword.Trim()!="")
        {
            string sql="select top 10* from WordList where word like '"+keyword.Trim().Replace("'","''")+"%'";
            SqlConnection conn=new SqlConnection(ConfigurationSettings.AppSettings["connectionString"]);
            conn.Open();
            DataTable dt=new DataTable();
            SqlCommand command=new SqlCommand(sql,conn);
            SqlDataAdapter adapter=new SqlDataAdapter(command);
            adapter.Fill(dt);
            conn.Close();

            foreach(DataRow row in dt.Rows)
            {
                string meaning=row["Meaning"].ToString();
                Response.Write("<strong>"+row["Word"].ToString()+"</strong> <i>");
				  Response.Write("row["Type"].ToString()+"</i>: "+meaning+"<br>");
            }
        }


    }

</script>


HTMLページ内のXMLHttpRequestオブジェクト

<html>
    <head>
        <script>
var req;

function Initialize()
{
    try
    {
        req=new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch(e)
    {
        try
        {
            req=new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch(oc)
        {
            req=null;
        }
    }

    if(!req&&typeof XMLHttpRequest!="undefined")
    {
        req= new
    XMLHttpRequest();

}

} function
SendQuery(key)
    {
    Initialize(); varurl="http://www.objectgraph.com/dictionary/dict.aspx?k="+key;

    if(req!=null)
    {
        req.onreadystatechange = Process;
        req.open("GET", url, true);
        req.send(null);

    }

}

function Process()
{
    if (req.readyState == 4)
        {
        // only if "OK"
            if (req.status == 200)
            {
                if(req.responseText=="")
                    HideDiv("autocomplete");
                else
                {
                    ShowDiv("autocomplete");
                    document.getElementById("autocomplete").innerHTML =req.responseText;
                }
            }
            else
            {
                document.getElementById("autocomplete").innerHTML=
					"There was a problem retrieving data:<br>"+req.statusText;
            }
        }
}

function ShowDiv(divid)
{
   if (document.layers) document.layers[divid].visibility="show";
   else document.getElementById(divid).style.visibility="visible";
}

function HideDiv(divid)
{
   if (document.layers) document.layers[divid].visibility="hide";
   else document.getElementById(divid).style.visibility="hidden";
}

function BodyLoad()
{
    HideDiv("autocomplete");
    document.form1.keyword.focus();

}
</script>
    </head>
    <body onload="BodyLoad();">
        <form name="form1">
        <input name="keyword" onKeyUp="SendQuery(this.value)" style="WIDTH:500px" autocomplete="off">
            <div align="left" class="box" id="autocomplete" style="WIDTH:500px;BACKGROUND-COLOR:#ccccff"></div>
        </form>

    </body>
</html>		

 

テキストボックス内でのkeyupのイベントはSendQueryメソッドのトリガーになっています。autocompleteを無効にしてる事に 注意してください。これをやらないと、IEのオートコンプリートと、divタグのレイヤーが被ってしまいます。 初期化のメソッドはXMLHttpRequestオブジェクトを作るだけです。 MozillaとSafariではこうするだけ

req=new XMLHttpRequest();

IEでは、ユーザーがインストールしてるMSXMLライブラリにしたがって作ります。 Processメソッドはイベントハンドラーとして活躍し、ウェブサーバーからのレスポンスが完了した跡にテキストを表示します。

オブザベーション

訳:武内樹一

(訳注:データベースの説明など、英英辞書の解説を基にしているため、英和のテーブル構造とは異なります)