web-dev-qa-db-ja.com

Typeahead v0.10.2&Bloodhound-ネストされたJSONオブジェクトの操作

[〜#〜]更新[〜#〜]

@BenSmithからの正解に基づいて( https://stackoverflow.com/users/203371/BenSmith )問題を見つけることができ、JSON階層を適切にナビゲートしていないことがわかりました。作業コードは次のとおりです。

        // instantiate the bloodhound suggestion engine
    var engine = new Bloodhound({
        datumTokenizer: function (datum) {
            return Bloodhound.tokenizers.whitespace(datum.title);
        },
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        prefetch: {
            url: "SampleData.json",
            filter: function (data) {
                //console.log("data", data.response.songs)
                return $.map(data.response.songs, function (song) {
                    return {
                        title: song.title,
                        artistName: song.artist_name
                    };
                });
            }
        }
    });

    // initialize the bloodhound suggestion engine
    engine.initialize();

    // instantiate the typeahead UI
    $('#prefetch .typeahead').typeahead(
      {
          hint: true,
          highlight: true,
          minLength: 1
      },
      {
          name: 'engine',
          displayKey: 'title',
          source: engine.ttAdapter(),
          templates: {
              empty: [
              '<div class="empty-message">',
              'unable to find any results that match the current query',
              '</div>'
              ].join('\n'),
              suggestion: Handlebars.compile('<p><strong>{{title}}</strong> by {{artistName}}</p>')
          }
      });

助けてくれてありがとう@BenSmith!


元の質問

TypeaheadとBloodhoundを使用するのは初めてです。ドキュメントはあまり役に立ちません。使用しているAPIから取得したJSONオブジェクトのセットがあります。 BloodhoundがJSONオブジェクトを理解できるように、JSONオブジェクトをナビゲートする方法を理解しようとしています。

ここでの目標は、ユーザーが曲名の入力を開始することです。オートコンプリートは、曲名とそれが実行されたアーティストのリストを表示します。

例:マストドンの真夜中のチャイム

各ライブラリの最新バージョンを使用しています: https://Twitter.github.io/typeahead.js/

サンプルJSON(SampleData.json):

 {"response":{"status":{"version": "4.2"、 "code":0、 "message": "Success"}、 "songs":[{"title": "真夜中のチャイム」、「artist_name」:「Mastodon」、「artist_foreign_ids」:[{"catalog": "7digital-AU"、 "foreign_id": "7digital-AU:artist:29785"}、{"catalog": " 7digital-UK "、" Foreign_id ":" 7digital-UK:artist:29785 "}]、" tracks ":[]、" artist_id ":" ARMQHX71187B9890D3 "、" id ":" SOKSFNN1463B7E4B1E "}、{" title ": "Down Under"、 "artist_name": "Men at Work"、 "artist_foreign_ids":[{"catalog": "7digital-AU"、 "foreign_id": "7digital-AU:artist:50611"}]、 "tracks" :[]、 "artist_id": "AR4MVC71187B9AEAB3"、 "id": "SORNNEB133A920BF86"}]}} 

このサイトを使用して http://json.parser.online.fr/ JSONを簡単にフォーマットします。

返されるJSONは常に同じ形式になりますが、含まれるデータは異なります。この例では、「トラック」はnullです。他の結果にはデータがあります。また、そのデータにもアクセスできる必要があります。

最新バージョンのJQueryを使用しています。これが私のhtmlページに含めたものです:

<script src="Scripts/jquery-2.1.1.min.js"></script>
<script src="Scripts/typeahead.bundle.min.js"></script>

HTMLは次のとおりです。

<div id="prefetch">
    <input class="typeahead" type="text" placeholder="Songs...">
</div>

スクリプトは次のとおりです。

    // instantiate the bloodhound suggestion engine
    var engine = new Bloodhound({
        datumTokenizer: function (d) { return Bloodhound.tokenizers.whitespace(d.tokens.join(' ')); },
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        prefetch: {
            url: "SampleData.json",
            filter: function (response) {
                return response.engine;
            }
        }
    });

    // initialize the bloodhound suggestion engine
    engine.initialize();

    // instantiate the typeahead UI
    $('#prefetch .typeahead').typeahead(
      {
          hint: true,
          highlight: true,
          minLength: 1
      },
      {
          name: 'songs',
          displayKey: function (engine) {
              return engine.songs.artist_name;
          },
          source: engine.ttAdapter()
      });

このコードを実行しようとすると、次のエラーが発生します。

Uncaught TypeError:undefinedのプロパティ「トークン」を読み取れません

ここでの助けや指示は大歓迎です。 Typeahead/Bloodhoundで作業しているJSONデータを取得する方法を知る必要があります。

ありがとう!

19
Jared

データムとして使用するjavascriptオブジェクトの配列を作成するように、フィルター関数を作成する必要があります。以下が機能するはずです(私はこれをテストしていません):

filter: function (response) {
            return $.map(response.songs, function (song) {
                return {
                    title: song.title,
                    artistName: song.artist_name
                };
            });
        }

(フィルター関数の例を見つけることができます ここ

そして、データムトークンを次のように変更します。

datumTokenizer: function (datum) {
        return Bloodhound.tokenizers.whitespace(datum.title);
    }

また、ディスプレイキーを次のように変更します。

displayKey: 'title'

これはTypeaheadが検索に使用するキーです。

提案リストに曲名とアーティストを表示する場合は、結果を表示するためにテンプレート(ハンドルバーなど)を使用することをお勧めします。 Typeaheadのサンプルページ の「カスタムテンプレート」の例を参照してください。提案のマークアップは次のようになります。

suggestion: Handlebars.compile('<p><strong>{{title}}</strong> by {{artistName}}</p>')
20
Ben Smith

私の答えは新しいものではありませんが、Twitterの先行入力のv0.11のアップデートにすぎません。いつものように、賛成票(ある場合)を元の回答にリダイレクトします。

Twitter-Typeaheadをまだ使用しているすべての人に、このリポジトリは維持されなくなったため、このリポジトリから移動することをお勧めします。代わりに、元のリポジトリのフォークである corejavascript/typeahead.js にリダイレクトし、同じ作成者(@JakeHarding)がこのリポジトリを維持します。

V0.10からv0.11にいくつかの変更が加えられたため、答えが必要です。これが、この新しいバージョンの新しいコードです。

[〜#〜] html [〜#〜]

_<div id="prefetch">
  <input class="typeahead" type="text" placeholder="Countries">
</div>
_

[〜#〜] js [〜#〜]

_    var tags = new Bloodhound({
        datumTokenizer: function(datum) {
            return Bloodhound.tokenizers.whitespace(datum.name);
        },
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        prefetch: {
            url: 'http://www.yourwebsite.com/js/data.json',
            cache: false,
            transform: function(response) {
                return $.map(response, function (tag) {
                    return {
                        name: tag.tagName,
                        id: tag.tagId
                    }
                });
            }
        }
    });

    $('#prefetch .typeahead').typeahead({
        minLength: 3,
        highlight: true
    }, {
        name: 'tags-dataset',
        source: tags,
        display: 'name'
    });
_

変化したこと:

  1. filterの下にprefetchオプションはありません。代わりに、transformを使用する必要があります。
  2. typeahead()関数の下のdisplayKeyは単にdisplayに変更されました。
  3. cacheオプションの下のtransformはfalseに設定されているため、データソースは毎回ロードされます。これはテストには適していますが、本番サーバーでは、データのキャッシュが必要な場合はこのオプションを無効にする必要があります。

cacheをtrueに設定してさまざまなデータソースでこの例を試している人々への追加のメモとして。新しいデータを取得できるように、コンソールで常にwindow.localStorage.clear();メソッドを実行して、既存のローカルストレージをクリアする必要があります。そうしないと、古いデータが使用されることになり、コードが機能しない理由を考えるかもしれません。

これが実用的な例です [〜#〜] jsfiddle [〜#〜] 開始するための例です。注意すべきいくつかのポイント:

  1. TypeaheadのCDNがあるかどうかわからなかったので、typeaheadjavascriptコード全体をそこに貼り付けました。ページの下部で、私の関数を見ることができます。
  2. データソースは、私のドロップボックスアカウントでホストされているファイルであるリンクを指しています。このファイルを削除した場合、この例はまったく機能しません。したがって、独自のソースを提供する必要があります。そのファイルの内容は次のとおりです-_[{"tagId":9,"tagName":"Action"},{"tagId":10,"tagName":"Adventure"},{"tagId":6,"tagName":"Books"},{"tagId":11,"tagName":"Fantasy"},{"tagId":2,"tagName":"Games"},{"tagId":1,"tagName":"Movies"},{"tagId":3,"tagName":"Music"},{"tagId":8,"tagName":"News"},{"tagId":4,"tagName":"Office"},{"tagId":5,"tagName":"Security"},{"tagId":7,"tagName":"TV-Shows"}]_
11
Rash