jQuery UIのAutocompleteでカテゴリー付きで入力候補を表示させる方法

今回はカテゴリー付きの入力候補を表示させる方法です。

jQuery UIのAutocompleteでカテゴリー付きで入力候補を表示させる方法

サンプル

HTMLコード

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8">
   <title>autocomplete demo</title>
   <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">
  <style>
  .ui-autocomplete-category {
    font-weight: bold;
    padding: .2em .4em;
    margin: .8em 0 .2em;
    line-height: 1.5;
  }
  </style>
   <script src="//code.jquery.com/jquery-1.12.4.js"></script>
   <script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <script>
  $( function() {
    $.widget( "custom.complete", $.ui.autocomplete, {
      _create: function() {
        this._super();
        this.widget().menu( "option", "items", "> :not(.ui-autocomplete-category)" );
      },
       /* items は response(suggest) で渡された suggest */
      _renderMenu: function( ul, items ) {
        var that = this,
        currentCategory = "";
        $.each( items, function( index, item ) {
          var li;
          if ( item.category != currentCategory ) {
            /* カテゴリーを追加 */
            ul.append( "<li class='ui-autocomplete-category'>" + item.category + "</li>" );
            currentCategory = item.category;
          }
          li = that._renderItemData( ul, item );
          if ( item.category ) {
            li.attr( "aria-label", item.category + " : " + item.label );
          }
        });
      }
    });
  var prefectures = [
{ label: "北海道",hira:"ほっかいどう",kata:"ホッカイドウ",roma:"Hokkaido",category:"北海道"},
{ label: "青森県",hira:"あおもりけん",kata:"アオモリケン",roma:"Aomori",category:"東北"},
{ label: "岩手県",hira:"いわてけん",kata:"イワテケン",roma:"Iwate",category:"東北"},
{ label: "宮城県",hira:"みやぎけん",kata:"ミヤギケン",roma:"Miyagi",category:"東北"},
{ label: "秋田県",hira:"あきたけん",kata:"アキタケン",roma:"Akita",category:"東北"},
{ label: "山形県",hira:"やまがたけん",kata:"ヤマガタケン",roma:"Yamagata",category:"東北"},
{ label: "福島県",hira:"ふくしまけん",kata:"フクシマケン",roma:"Fukushima",category:"東北"},
{ label: "茨城県",hira:"いばらきけん",kata:"イバラキケン",roma:"Ibaraki",category:"関東"},
{ label: "栃木県",hira:"とちぎけん",kata:"トチギケン",roma:"Tochigi",category:"関東"},
{ label: "群馬県",hira:"ぐんまけん",kata:"グンマケン",roma:"Gunma",category:"関東"},
{ label: "埼玉県",hira:"さいたまけん",kata:"サイタマケン",roma:"Saitama",category:"関東"},
{ label: "千葉県",hira:"ちばけん",kata:"チバケン",roma:"Chiba",category:"関東"},
{ label: "東京都",hira:"とうきょうと",kata:"トウキョウト",roma:"Tokyo",category:"関東"},
{ label: "神奈川県",hira:"かながわけん",kata:"カナガワケン",roma:"Kanagawa",category:"関東"},
{ label: "新潟県",hira:"にいがたけん",kata:"ニイガタケン",roma:"Niigata",category:"中部"},
{ label: "富山県",hira:"とやまけん",kata:"トヤマケン",roma:"Toyama",category:"中部"},
{ label: "石川県",hira:"いしかわけん",kata:"イシカワケン",roma:"Ishikawa",category:"中部"},
{ label: "福井県",hira:"ふくいけん",kata:"フクイケン",roma:"Fukui",category:"中部"},
{ label: "山梨県",hira:"やまなしけん",kata:"ヤマナシケン",roma:"Yamanashi",category:"中部"},
{ label: "長野県",hira:"ながのけん",kata:"ナガノケン",roma:"Nagano",category:"中部"},
{ label: "岐阜県",hira:"ぎふけん",kata:"ギフケン",roma:"Gifu",category:"中部"},
{ label: "静岡県",hira:"しずおかけん",kata:"シズオカケン",roma:"Shizuoka",category:"中部"},
{ label: "愛知県",hira:"あいちけん",kata:"アイチケン",roma:"Aichi",category:"中部"},
{ label: "三重県",hira:"みえけん",kata:"ミエケン",roma:"Mie",category:"中部"},
{ label: "滋賀県",hira:"しがけん",kata:"シガケン",roma:"Shiga",category:"関西"},
{ label: "京都府",hira:"きょうとふ",kata:"キョウトフ",roma:"Kyoto",category:"関西"},
{ label: "大阪府",hira:"おおさかふ",kata:"オオサカフ",roma:"Osaka",category:"関西"},
{ label: "兵庫県",hira:"ひょうごけん",kata:"ヒョウゴケン",roma:"Hyogo",category:"関西"},
{ label: "奈良県",hira:"ならけん",kata:"ナラケン",roma:"Nara",category:"関西"},
{ label: "和歌山県",hira:"わかやまけん",kata:"ワカヤマケン",roma:"Wakayama",category:"関西"},
{ label: "鳥取県",hira:"とっとりけん",kata:"トットリケン",roma:"Tottori",category:"中国"},
{ label: "島根県",hira:"しまねけん",kata:"シマネケン",roma:"Shimane",category:"中国"},
{ label: "岡山県",hira:"おかやまけん",kata:"オカヤマケン",roma:"Okayama",category:"中国"},
{ label: "広島県",hira:"ひろしまけん",kata:"ヒロシマケン",roma:"Hiroshima",category:"中国"},
{ label: "山口県",hira:"やまぐちけん",kata:"ヤマグチケン",roma:"Yamaguchi",category:"中国"},
{ label: "徳島県",hira:"とくしまけん",kata:"トクシマケン",roma:"Tokushima",category:"四国"},
{ label: "香川県",hira:"かがわけん",kata:"カガワケン",roma:"Kagawa",category:"四国"},
{ label: "愛媛県",hira:"えひめけん",kata:"エヒメケン",roma:"Ehime",category:"四国"},
{ label: "高知県",hira:"こうちけん",kata:"コウチケン",roma:"Kochi",category:"四国"},
{ label: "福岡県",hira:"ふくおかけん",kata:"フクオカケン",roma:"Fukuoka",category:"九州"},
{ label: "佐賀県",hira:"さがけん",kata:"サガケン",roma:"Saga",category:"九州"},
{ label: "長崎県",hira:"ながさきけん",kata:"ナガサキケン",roma:"Nagasaki",category:"九州"},
{ label: "熊本県",hira:"くまもとけん",kata:"クマモトケン",roma:"Kumamoto",category:"九州"},
{ label: "大分県",hira:"おおいたけん",kata:"オオイタケン",roma:"Oita",category:"九州"},
{ label: "宮崎県",hira:"みやざきけん",kata:"ミヤザキケン",roma:"Miyazaki",category:"九州"},
{ label: "鹿児島県",hira:"かごしまけん",kata:"カゴシマケン",roma:"Kagoshima",category:"九州"},
{ label: "沖縄県",hira:"おきなわけん",kata:"オキナワケン",roma:"Okinawa",category:"沖縄"}  
      ];
    $( "#prefecture" ).complete({
        source: function(request, response) {
                   var searchStr = request.term; /* 入力文字列取得 */
                   var suggest = new Array();
                   $.each(prefectures, function(index, value){
                        if ( value.label.match(searchStr)        /* 漢字で検索 */
                            || value.hira.match(searchStr)      /* ひらがなで検索 */
                            || value.kata.match(searchStr)      /* カタカナで検索*/
                            || value.roma.toUpperCase().match(searchStr.toUpperCase()) /* ローマ字で検索 */
                        ) {
                           /* 漢字を入力候補として表示させるために配列に設定 */
                           suggest.push(value);
                        }
                   });
                   response(suggest);  /* 結果を設定 */
                }
    });
  } );
  </script>

</head>
<body><span id="lblCount"></span>
   <div class="ui-widget">
      <label for="prefecture">都道府県: </label> <input id="prefecture" type="text" />
   </div>
</body>
</html>

デモ

カテゴリー付きの入力候補を表示

カテゴリーと入力候補を定義

まず、カテゴリーと入力候補を定義します。

  var prefectures = [
{ label: "北海道",hira:"ほっかいどう",kata:"ホッカイドウ",roma:"Hokkaido",category:"北海道"},
{ label: "青森県",hira:"あおもりけん",kata:"アオモリケン",roma:"Aomori",category:"東北"},
{ label: "岩手県",hira:"いわてけん",kata:"イワテケン",roma:"Iwate",category:"東北"},
{ label: "宮城県",hira:"みやぎけん",kata:"ミヤギケン",roma:"Miyagi",category:"東北"},
...
{ label: "宮崎県",hira:"みやざきけん",kata:"ミヤザキケン",roma:"Miyazaki",category:"九州"},
{ label: "鹿児島県",hira:"かごしまけん",kata:"カゴシマケン",roma:"Kagoshima",category:"九州"},
{ label: "沖縄県",hira:"おきなわけん",kata:"オキナワケン",roma:"Okinawa",category:"沖縄"} 
      ];

構造体の配列を定義し、表示は「label」に、分類は「category」定義しました。

また、「hira」には、検索時に利用するひらがなの定義、「kata」にはカタカナ、「roma」にはローマ字の定義を入れておきます。

入力時、漢字/ひらがな/カタカナ/ローマ字検索

テキストボックスに入力があると、入力候補の検索を、漢字/ひらがな/カタカナ/ローマ字で検索を試みて、ヒットする場合には、対象レコードの構造体を配列変数に格納し、responseに設定します。

    $( "#prefecture" ).complete({
        source: function(request, response) {
                   var searchStr = request.term; /* 入力文字列取得 */
                   var suggest = new Array();
                   $.each(prefectures, function(index, value){
                        if ( value.label.match(searchStr)        /* 漢字で検索 */
                            || value.hira.match(searchStr)      /* ひらがなで検索 */
                            || value.kata.match(searchStr)      /* カタカナで検索*/
                            || value.roma.toUpperCase().match(searchStr.toUpperCase()) /* ローマ字で検索 */
                        ) {
                           /* 漢字を入力候補として表示させるために配列に設定 */
                           suggest.push(value);
                        }
                   });
                   response(suggest);  /* 結果を設定 */
                }
    });

カテゴリー付きの入力候補生成

  $( function() {
    $.widget( "custom.complete", $.ui.autocomplete, {
      _create: function() {
        this._super();
        this.widget().menu( "option", "items", "> :not(.ui-autocomplete-category)" );
      },
       /* items は response(suggest) で渡された suggest */
      _renderMenu: function( ul, items ) {
        var that = this,
        currentCategory = "";
        $.each( items, function( index, item ) {
          var li;
          if ( item.category != currentCategory ) {
            /* カテゴリーを追加 */
            ul.append( "<li class='ui-autocomplete-category'>" + item.category + "</li>" );
            currentCategory = item.category;
          }
          li = that._renderItemData( ul, item );
          if ( item.category ) {
            li.attr( "aria-label", item.category + " : " + item.label );
          }
        });
      }
    });

「 source 」の最後で『response(suggest)』されると、次に「_renderMenu」が呼び出されます。

入力候補のメニューを生成する処理となります。

まず、入力候補対象の「items」を$.eachを使って読んでいきいます。1件1件読んでいき、カテゴリーが変わった場合には、liを追加し、カテゴリーを追加するようになっています。

サンプルのデモ

まず、漢字で「川」と入力すると、3つの県がヒットし、エリアのカテゴリーも表示されます。

次に英字で「A」と入力するとたくさんの都道府県がヒットします。

ちゃんとエリアごと都道府県がまとめられて入力候補として表示されますね。

以上、ご参考まで。