yamachan Ajax/.NET/C# メモ

2007-02-27

[Ajax] 入力フィールドにSuggest機能をつけてみる (2)

週末に時間がとれましたので、前回 の Suggest機能を書き直してみました。 今回はわりと JavaScript っぽくなってきている、気がする。

本サイト右上の検索バーには反映されています。 今のところ、見た目の違いは選択キーワードの背景がグレーになったぐらいですかね。

Suggest付の検索ボックスの例

まずは検索バーの html なんですが、よりシンプルになっています。

<form action="http://www.google.co.jp/search">
<input name="q" size="20" id="my-field" />
<input name="q" type="hidden"
value=" site:http://yamachan-cs.blogspot.com/"/>
<img src="search_glass.gif" alt="Search"
width="48" height="24" align="bottom"
onclick="document.getElementById('my-field')
.form.submit();"
</form>

<div id="my-help"
style="visibility:hidden;display:none;color:blue">
</div>

この部分にはJavaScriptが使用されていない、のが今回のポイントです。 普通の検索バーと違うのは、div要素 "my-help" がひそかに追加されていることぐらいですね。

引き続きましては、Suggest機能を追加する JavaScript 部分です。 辞書の定義部分をのぞけば、記述は1行とシンプルになっていますね。 これで動作します。

<script>
var dic = [
"Ajax",
"aptana",
...途中省略
"unescapeHTML"
];

var ys=new jp.rinco.Suggest('my-field','my-help',dic);
</script>

ただ、このままでは地味ですので、少し拡張してみましょう。 Suggestされたキーワードにマウスがくると、文字は赤色に、背景は灰色になるようにロジックを追加します。

作成したSuggestオブジェクトの onmouseover, onmouseout 関数を、オーバーライドすればOKです。 記述する処理は、ごく普通ですね~

<script>
ys.onmouseover = function() {
this.style.color = 'red';
this.style.backgroundColor = '#ddd';
}
ys.onmouseout = function() {
this.style.color = 'blue';
this.style.backgroundColor = 'white';
}
</script>

これで jp.rinco.Suggest オブジェクトの使い方の説明は終わりです。 前回からの改良点としては、利用方法・拡張方法がシンプルになったこと、そして1ページに複数利用することが可能になったことでしょうか。

実際のコードを簡単にご紹介します。 まずはオブジェクトの生成の部分です。

jp.rinco.Suggest = function(t, h, d) {
if (typeof(t) == 'string')
this.target = document.getElementById(t);
else
this.target = t;
if (typeof(h) == 'string')
this.help = document.getElementById(h);
else
this.help = h;
this.dic = d;

this.target.aYamachanSuggest = this;
this.target.onkeyup = function() {
this.aYamachanSuggest.updateHelp();
}
}

対象のフィールドやヘルプ領域は、id で指定しても、オブジェクトを直接指定してもOKです。 対象フィールドのオブジェクトに aYamachanSuggest なんて名前で、勝手に自分自身を登録しちゃってるのがトリッキーかもしれません。

引き続き、Java でいうところのインスタンス・メソッドの定義部分をご紹介します。 実際には、上記の生成部分に含まれて記述しています。

まずはSuggestキーワードをヘルプ領域に追加するための、keyElement() 補助関数です。

this.keyElement = function(k) {
var ke = document.createElement('div')
ke.innerHTML = k;
ke.aYamachanSuggest = this;
ke.onclick = function(){
this.aYamachanSuggest.click(this);
}
if (ke.aYamachanSuggest.onmouseover)
ke.onmouseover = ke.aYamachanSuggest.onmouseover;
if (ke.aYamachanSuggest.onmouseout)
ke.onmouseout = ke.aYamachanSuggest.onmouseout;
return ke;
}

で、実際にヘルプ領域を更新して表示/非表示する updateHelp() 関数です。

this.updateHelp = function() {
var k = jp.rinco.lastWord(this.target.value);
if (k == "") {
this.help.style.visibility = 'hidden';
this.help.style.display = 'none';
return;
}

var lk = k.toLowerCase();
var counter = 0;
this.help.innerHTML = "";

for (loop = 0; loop < this.dic.length; loop++) {
var dk = this.dic[loop];
if (dk.toLowerCase().indexOf(lk) == 0) {
this.help.appendChild(this.keyElement(dk));
counter++;
}
}

if (counter > 0) {
this.help.style.visibility = 'visible';
this.help.style.display = 'block';
} else {
this.help.style.visibility = 'hidden';
this.help.style.display = 'none';
}
}

最後は Java でいうクラス・メソッドのご紹介です。 ついに登場した prototype って感じですね。これは生成部分の外で記述されています。

click() は、Suggestキーワードがクリックされたときに呼び出される関数です。

jp.rinco.Suggest.prototype.click = function(ke) {
var te = ke.aYamachanSuggest.target;
var k = jp.rinco.lastWord(te.value);
if (k == "") return;

te.value=te.value.substring(0,te.value.length-k.length)
+ ke.innerHTML;
ke.aYamachanSuggest.updateHelp();
te.focus();
}

以上、まだ不安な部分は残しているものの、まぁ JavaScript で書いたプログラムだと言えるレベルになってきたのではないかと...。 そして僕も「趣味のJSプログラマーです」と言っても怒られないかも、というレベルに?