Googleサジェストが実装できるjQuery Autocomplete Mod | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

jQuery Autocomplete Mod はjQueryベースのプラグインで、テキストボックスに入力した情報を元に、Googleサジェストのような機能を簡単に実現することができます。

Ajaxを使って外部プログラムと通信しながら情報を取得し、候補をユーザーに表示することができるほか、予めJavaScript内に定義していた情報から入力された情報を補完するというような使い方もできます。



jQuery Autocomplete Modの設置方法


設置方法は、jQuery Autocomplete Mod のサイトから、下記3つのファイルをダウンロードします。


jquery.autocomplete.js


本体となるJavaScript


jquery.autocomplete.css


検索結果のフォームを表示するためのCSS


indicator.gif


サイト上ではリンクが掲載されていないのですが、検索候補のローディング時に表示する画像。(なくても支障はありません)


これら、3つのファイルをダウンロードし、設置したいサーバー上にアップロードします。

設置場所は、任意でかまいませんがローディング用の画像は、CSS内にパスが書かれているので(デフォルトはCSSと同じディレクトリ)、変更したい場合は修正しておきます。


準備が整ったら、jQuery Autocomplete Modを組み込みたいHTMLを作ります。

今回は、単純に検索ボックスとボタンを用意したシンプルなものです。


<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
<script type="text/javascript" src="./jquery.js"></script>
<script type="text/javascript" src="./jquery.autocomplete.js"></script>
<link rel="stylesheet" type="text/css" href="./jquery.autocomplete.css">
<script type="text/javascript">
$(document).ready(function(){
    $('#search_box').autocomplete('autocomplete.php');
});
</script>
</head>
<body>
<input type="text" name="search" id="search_box" />
<input type="button" value="search" />
</body>
</html>


まず、jQuery本体とjQuery Autocomplete ModのJavaScriptとCSSファイルを読み込むようにします。

次に、jQueryを使用する際に書くお決まりの決まり文句($(document).ready)の中で、使いたい検索ボックスのIDを指定してメソッドを呼び出します。
引数に指定しているのは、Ajaxで通信する先のプログラム名で、今回はautocomplete.phpを呼び出しています。


PHPのプログラム側はどういうものかというと、


<?php

$prefectures = array("あいち",
                     "あおもり",
                     "あきた",
                     "おおさか",
                     "おかやま",
                     "おきなわ");

if (!empty($_GET['q'])) {

    $parameter = explode(" ", mb_convert_encoding($_GET['q'], "EUC-JP", "UTF-8"));

// スペース区切りで検索された場合は、最後のキーワードを検索対象にする
    $search_word = array_pop($parameter);

    $reply = NULL;

    if (!empty($search_word)) {
        foreach ($prefectures as $word) {
// 検索キーワードが含まれている情報を取り出し
            $find = stristr($word, $search_word);
            if ($find !== FALSE) {
                $reply = $reply . $find . "\n";
            }
        }

// ヒットするのものがあればUTF-8に変換して出力する
        if ($reply !== NULL) {
            $result = mb_convert_encoding($reply, "UTF-8", "EUC-JP");
            echo $result;
        }
    }
}

今回は、PHPプログラムだけで検索フォームから受信したキーワード(都道府県)に対する候補を返す仕様にしています。

実際は、DBなどから引っ張ってきて返すプログラムを書いておけばよいと思います。


jQuery Autocomplete Modは、qというパラメータで情報を送信するので、$_GET['q']でキーワードを受け取り、その言葉を含む情報をechoで出力するようにしています。

複数ある場合は、改行キーを入れて出力すれば複数候補を検索フォーム上に表示することができます。

(文字コードをUTF-8で返す必要があります)

繰り返しになりますが、stristr 関数を使って検索しているだけなので、正確な情報を返す仕様のプログラムではありません。


- 検索結果の例
A Day In The Boy&#39;s Life-jQueryAutocompleteMod-1



jQuery Autocomplete Modをカスタマイズする


このまま利用していても良いのですが、幾つか使いにくい点があるので、jquery.autocomplete.jsをカスタマイズをして見ます。


・ キーワードの候補を表示する際に、最低入力する文字数を変更したい


デフォルトだと、1文字入力しただけでキーワード候補を表示する仕様になっています。

あまりに頻繁に通信されるとパフォーマンス上よくない、ということであれば最低何文字入力したら候補を表示するかを変更することができます。


$('#search_box').autocomplete('autocomplete.php', {
    minChars: 2
});


メソッドを呼び出す際に、上記のようにプロパティを指定します。

上記の場合は、2文字以上入力しないとキーワード候補が表示されなくなります。


・ Ajaxで通信する際にキーワード以外のパラメータを渡したい


デフォルトだと、キーワードをqというパラメータで指定したプログラムへ送信します。

これ以外に送信したいパラメータがある場合は、下記のように指定します。


$('#search_box').autocomplete('autocomplete.php', {
    extraParams: { foo: 'bar' }
});


上記の場合は、fooというパラメータ名でbarというデータをキーワード情報と一緒にautocomplete.phpへ渡してくれます。


・ 検索候補の中から選択しても、繰り返し検索できるようにする


デフォルトだと、一度検索候補の中からキーワードを選択してしまうと、取り消して再度別のキーワード候補を表示するということができません。

それを可能にするには、jquery.autocomplete.js内の下記の箇所を変更します。


options.cacheLength = options.cacheLength || 0;


上記のプロパティは、検索フォームの中で指定できるのですが、なぜか反映されないので、直接JavaScript本体を修正するようにしています。


・ キーワード候補を確定させたときに、検索ボックスからフォーカスが外れないようにする


表示されるキーワード候補の中から選択すると、検索ボックスからフォーカスが外れる仕様になっています。

これだと、続けて検索する(後述)のようなことも難しいので、そのまま検索ボックス内にフォーカスしたままになるように変更します。


87         case 13: // return
88             if( selectCurrent() ){
89                 // make sure to blur off the current field
90 //              $input.get(0).blur();

313         ).click(function(e) { e.preventDefault(); e.stopPropagation(); selectItem(this); $input.get(0).focus(); });


本体のJavaScriptコードの90行目辺りに書かれているblur()をコメントアウトし、313行目辺りに書かれているロジックにforcus()を追加しています。


・ 複数のキーワードを並べても候補を表示できるようにする


Googleで検索するときのようにスペース区切りで複数のキーワードを並べても候補の表示と選択ができるようにしてみます。
先ほど書いた、通信先のautocomplete.phpでは、スペース区切りだった場合、分割して最後のキーワードに該当する候補を返す仕様にしています。


一方、jQuery Autocomplete Mod本体では、選択したキーワード候補を確定すると、検索ボックスにそのキーワードのみしか表示してくれません。

スペースで区切った場合、前回のキーワードを残しつつ、新たに入力したキーワードで検索して候補を表示するようにしてみます。


178         prev = v;
179
180         var set_data = '';
181         var prev_box_data = $input.val().split(' ');
182         var word_cnt = prev_box_data.length;
183         if (word_cnt > 1) {
184             for (i = 0; i < word_cnt; i++) {
185                 if (i == 0) {
186                     set_data = prev_box_data[i];
187                 } else if (i == (word_cnt - 1)) {
188                     set_data += ' ' + prev;
189                 } else {
190                     set_data += ' ' + prev_box_data[i];
191                 }
192             }
193         } else {
194             set_data = v;
195         }
196
197         $results.html("");
198         $input.val(set_data);


178行目辺りを上記のようなロジックに変更します。

やってることは、検索ボックスに入力された情報($input.val)をスペースで分割し、それまで入力されていた情報と今回新たに候補から選択された情報を合わせて、再び検索ボックスにセットするということをしています。


- 検索例
A Day In The Boy&#39;s Life-jQueryAutocompleteMod-2


若干、Googleサジェストとは挙動が違うのですが、スペースを入れた場合、そこから新しく別のキーワードで候補を表示しています。

本当に、Googleサジェストのようにしたければ、候補を検索して返すautocomplete.php側で、渡された情報を全て結合して返すような仕様にすればよいと思います。


検索ボックスも、こういう風な実装をしておけば、ユーザーも便利に使えるかもしれませんね。