JavaScript で入力補完を行う suggest.js を Ajax 対応する



Webアプリケーションで、途中まで入力したら候補を
リストで表示する処理を実装したかったのですが、
いかんせん、JavaScriptの知識はほとんどゼロ。

いろいろ探し回ってみると、suggest.jsという
ライブラリを見つけました。

残念ながら、suggest.jsは変換候補を事前にJavaScriptに仕込んでおく
必要があるようで、今回はデータベースに登録されている候補から
選択させたかったので、若干要件にあいません。

さらに調べてみると、suggest_ajax.jsというsuggest.jsを
ajax対応する拡張スクリプトを見つけました。

早速使用してみたのですが・・・suggest.jsがバージョンアップの際、
オブジェクト名を変更されたようで動きません。

覚悟を決めて、自分でajax対応することにしました。

suggest.jsに変更を加えないように書いたスクリプトがコチラ。

■search.js
blogへの登録時、エラーになるので、open、evalの始めの文字は全角にしてます。


function createXmlHttpRequest() {
    var xmlhttp = false;
    if( window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest();
    } else if(window.ActiveXObject) {
        try {
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch(e) {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    return xmlhttp;
}

var xmlhttp = 0;
var sg = null;

function initSuggest(suggest_obj) {
    sg = suggest_obj;
    //区切り文字を変更
    sg.delim = '、';
    //検索ロジックを上書きして、何もしないように変更
    sg._search = function (text) { return 0; };
    //検索時のフック関数を指定
    sg.hookBeforeSearch = getList;
}

//HTTP通信
function stateChange() {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        var rst = xmlhttp.responseText;
        //受け取ったデータを配列に変換し、格納
        sg.candidateList = eval(rst);
        //データ件数取得
        var list_count = sg.candidateList.length;
        //候補リストインデックスを一旦削除
        sg.suggestIndexList = [];
        //検索結果が取得できている場合
        if (list_count != 0) {
            //インデックスを作成する
            for (i = 0; i < list_count; i++){
                sg.suggestIndexList.push(i);
            }
            //リストの表示
            sg.createSuggestArea(sg.candidateList);
        }
    }
}

function getList (text) {
    
    if (sg == null){
        return [];
    }
    sg.candidateList = [];
    if (! xmlhttp) xmlhttp = createXmlHttpRequest();

    if (! xmlhttp || xmlhttp.readyState == 1 ||
        xmlhttp.readyState == 2 || xmlhttp.readyState == 3){
        return [];
    }
    var query = encodeURI(text);
    //webサーバへ問い合わせ
    xmlhttp.open("GET", "search.php?" + query, true);
    xmlhttp.onreadystatechange = stateChange;
    xmlhttp.send(null);
}




サンプルのhtml

■index.html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="Content-Script-Type" content="text/javascript" />
    <title>候補出力サンプル</title>
    <style type="text/css">
      <!--
        #suggest {
          position: absolute;
          background-color: #FFFFFF;
          border: 1px solid #CCCCFF;
          width: 252px;
        }
        #suggest div {
          padding: 1px;
          display: block;
          width: 250px;
          overflow: hidden;
          white-space: nowrap;
        }
        #suggest div.select{
          color: #FFFFFF;
          background-color: #3366FF;
        }
        #suggest div.over{
          background-color: #99CCFF;
        }
        -->
    </style>

    <script type="text/javascript" src="suggest.js"></script>
    <script type="text/javascript" src="search.js"></script>
    <script type="text/javascript" language="javascript">
    <!--
      // wondowのonloadイベントでSuggestを生成
      function start(){
      sg = new Suggest.LocalMulti("text", "suggest", [], {dispAllKey: true});
      initSuggest(sg);
      };
      window.addEventListener ?
        window.addEventListener('load', start, false) :
        window.attachEvent('onload', start);
    //-->
    </script>
  </head>
  <body>
    <h1>名称候補 サンプル</h1>
      <p>IMEモードをOFFにして入力してください。</p>
      <input id="text" type="text" name="pattern" value="" autocomplete="off" size="40" style="display: block"/>
      <!-- 補完候補を表示するエリア -->
      <div id="suggest"></div>
  </body>
</html>



検索を実行するphpはこんな感じ

■search.php


<?php
//これで、画面上で入力されている文字が取れる
$keyword = urldecode($_SERVER['QUERY_STRING']);
header("Content-type: text/plain charset=\"UTF-8\"");
if ($keyword == 'a') {
echo urldecode("['名前の','リストを','作成','します']");
} else {
echo urldecode("['本当は','データベースを','検索して','結果を','作成します']");
}
?>


これで、テキストボックスに"a"と入力したときと、それ以外の文字を
入力したときでリストの内容が変更されます。

動作はこんな感じ





※JavaScript初心者なので、致命的な障害があるかもです。


【参考URL】
suggest.js - 入力補完ライブラリ
http://www.enjoyxstudy.com/javascript/suggest/

suggest_ajax.js - suggest.jsをAjaxなどに対応する等の拡張スクリプト公開
http://blog.yappo.jp/yappo/archives/000376.html

作って理解するAjax
http://itpro.nikkeibp.co.jp/article/COLUMN/20060110/227005/?ST=nettech



もどる