no-image

jQuery UI + Python で ajax な autocomplete

社内向けシステムの使い勝手向上と、今後のシステム開発に向けてフォームにオートコンプリートをつけようと苦戦した記録。

静的候補を表示する

jQuery で autocomplete を実現しようとすると jQuery UI のお世話になる。参考にしたページはこちら。

最も簡潔な実装方法は、フォームと同じファイルにリストを用意する方法。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/base/jquery-ui.css">
https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js

$(function() {
    var data = [
        'にんじん',
        'たまねぎ',
        'じゃがいも',
        'きゅうり'
    ];
    
    $('#item').autocomplete({
        source: data
    });
});

<title>autocomplete のサンプル</title>
</head>
<body>
<input type="text" id="item" value="" />
</body>
</html>

最も簡潔な例はこんな感じ。単に配列を用意するだけ。

Ajax で動的に候補を読み込む

これも同じサイトの別記事を参考にした。

$(function() {
    $('#item').autocomplete({
        source: './autocomplete.py'
    });
});

パラメータ "source" を候補を取得する CGI 等にするだけで OK. CGI 側は候補を JSON で返せば良い。クライアント側の実装はこれで完了なのだが、サーバ側の実装で苦戦したのでそれについて記述する。

動的候補を用意するサーバ側の実装

今回は実装しているサーバの都合で Python による実装としている。(余談だが、PHP 使わなかったのは Linux PHP + FreeTDS + Windows SQL Server という特殊な環境でどうしても PHP のドライバが落ちて使えなかったから。ソースを修正してリビルド……というところまでしたけど、実用に持っていくのに手間がかかりすぎて使い慣れた Python  に逃げた)

今になって冷静に読んでみると参考ページには書いてあるのだが、初めクライアントからの入力途中の値を得るのにフィールドの名前がわからずに随分と彷徨った。答えは簡単で、 term というフィールドがそれだ。

なので例えば Python であれば

import cgi

form = cgi.FieldStorage()
term = form.getfirst('term')

という感じで取得する。

取得した term を使ってデータベースなどに照会をかけて、得られた結果をクライアントに JSON 形式で返す。

以下は簡潔にするため固定値の場合。

import json

data = [
    {label: 'にんじん', value: '00000001'},
    {label: 'たまねぎ', value: '00000002'},
    {label: 'きゅうり', value: '00000003'}
]

print('Content-type: application/json; charset=UTF-8\r\n')
print(json.dumps(data))

Content-type を出力していないと 500: Internal Server Error をはいてしばらく悩んだ。

Ajax でのデバッグは通信内容が目に見えないことも多いので、例えば IE なら F12 キーで Web 開発ツールを起動して Network の通信内容を見てみると原因を特定しやすい。