UIプロトタイプ:autocomplete (jQuery plug-in jSuggest)
2010.01.08
昨日に引き続いて、今日も作成中の 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ライブラリのために丸一日費やすのは厳しいところだが、こういった部品レベルで手を抜くと後々痛いめに合うのでしかたがない。アプリへの組み込みは明日だ。
http://code.drewwilson.com/entry/autosuggest-jquery-plugin
これじゃダメなんですか?
Posted by: icloud | 2010.01.09 at 06:18
keyDown じゃなくて keypressで return false するとform のsubmit キャンセルできるようです
$('input').bind('keypress',function(evt){
if(evt.keyCode == 13){ //ENTER
return false;
}
});
Posted by: cyokodog | 2010.01.10 at 08:15