プロトタイプ:AJAXで改良するフォーム入力
無名関数を使った非同期通信のススメ(JavaScript)

UIプロトタイプ:autocomplete (jQuery plug-in jSuggest)

 昨日に引き続いて、今日も作成中の Google App Engine アプリ用のUI部品の作成。HTMLの一部に記述された(もしくは別途JSONで取得した)ワード・リストの入力を autocomplete を使って簡単にしようという試み(Google Suggestのようにダイナミックにリストを取得する必要はない)。

 そこで、まずは既存のライブラリ・プラグインの調査から。必要とする人も多いようで、少し調べただけで20個ぐらい見つかる。デモを見て5つに絞ってからそれぞれのソースコードを解析。例によってどうしようもない品質のコードもあるので、結局のところたどり着いたのは、比較的コードがきれいなこの二つ。

 どちらかをそのまま使っても良かったのだが、どちらもリストをダイナミックにサーバーから取得するシナリオに最適化されている点が気に入らないし、コーディング・スタイルが私のものと違いすぎる。ということで結局一から作り直すことに。

 例によって「HTMLはView、JavaScriptはController」というモデルを厳密に守るためには、候補のリストはHTMLの一部に記述できなければいけない。

        <div class='suggest'>

            <input type="text" name="month" id="month" autocomplete="off" />

            <ul>

                <li>January</li>

                <li>Februrary</li>

                <li>March</li>

                <li>April</li>

                <li>May</li>

                <li>June</li>

                <li>July</li>

                <li>August</li>

                <li>September</li>

                <li>October</li>

                <li>November</li>

                <li>December</li>

            </ul>

        </div>

 もちろん、スタイルシートには、".suggest ul { display:none }" と書いて初めは隠しておく。

.suggest ul {

    color: #333;

    display: none;

    width: 15em;

    position: absolute;

    border: solid 1px #777;

    background: white;

    -webkit-box-shadow: 3px 3px 5px #888;

}

.suggest li {

    list-style: none;

    cursor: pointer;

}

.js_selected {

    background: #ccf;

}

.js_match {

    color: #000;

    font-weight: bold;

}

.js_hover {

    background: #99f;

}

 JavaScriopt側は以下の三行。

$(document).ready(function() {

    $('.suggest').JSuggest();

});    

 実際に動作するデモは下に貼付けてあるのでお試しいただきたい(いつものように、Safari4, Firefox3.5, IE7, Opera9で動作確認済み)。

 一番苦労したのが、Operaブラウザー上で、リストから一つ選択するためにEnterを押した時にformをsubmitしてしまうという問題を回避する部分。jQueryのkeydownイベントにfalseを返してもなぜかsubmitしてしまうのだ。同じ問題に直面した人も多かったようで、それを参考に解決。

 ちなみに、このプラグイン(ソースはこちらーMITライセンス、ドキュメントなし)を作るのに費やした時間は約9時間。既存のライブラリの調査に3時間、コーディングに4時間、各種ブラウザーでのテストとバグ取りに2時間、というところか。結構大きめのウェブアプリを1ヶ月で作ろうとしている中で、たった一つのUIライブラリのために丸一日費やすのは厳しいところだが、こういった部品レベルで手を抜くと後々痛いめに合うのでしかたがない。アプリへの組み込みは明日だ。

Comments

icloud

http://code.drewwilson.com/entry/autosuggest-jquery-plugin
これじゃダメなんですか?

cyokodog

keyDown じゃなくて keypressで return false するとform のsubmit キャンセルできるようです
$('input').bind('keypress',function(evt){
if(evt.keyCode == 13){ //ENTER
return false;
}
});

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been posted. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

Your Information

(Name is required. Email address will not be displayed with the comment.)