Typeahead v0.10.2 & Bloodhound - travailler avec des objets JSON emboîtés

UPDATE

basé sur la bonne réponse de @BenSmith (https://stackoverflow.com/users/203371/BenSmith) j'ai pu trouver mon problème et j'ai découvert que je ne naviguais pas correctement dans ma hiérarchie JSON. Voici le code qui fonctionne:

        // 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>')
          }
      });

Merci @BenSmith pour votre aide!


Question Originale

je commence à travailler avec Typeahead et Bloodhound. Le la documentation n'est pas très utile. J'ai un ensemble d'objets JSON que je récupère d'une API avec laquelle je travaille. J'essaie de trouver comment naviguer à travers mes objets JSON pour que ce Limier puisse les comprendre.

le but ici est qu'un utilisateur commence à taper un nom de chanson. L'autocomplete affichera alors une liste de noms de chansons et de l'artiste qui l'a jouée.

Par Exemple: sonneries à minuit par Mastodon

je suis en utilisant le dernières versions de chaque bibliothèque: https://twitter.github.io/typeahead.js/

l'échantillon JSON (SampleData.json):

{"response": {"status": {"version": "4.2", "code": 0, "message": "Success"}, "songs": [{"title": "Chimes At Midnight", "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"}]}}

utilisez ce site http://json.parser.online.fr/ pour formater le JSON facilement.

le JSON que je vais récupérer sera toujours dans le même format, mais contiendra des données différentes. Dans cet exemple, les "pistes" sont nulles. D'autres résultats ont des données. Il me faudrait aussi pouvoir accéder à ces données en tant que bien.

j'utilise la dernière version de JQuery. Voici ce que j'ai inclus dans ma page html:

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

voici le HTML:

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

Voici le script:

    // 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()
      });

Lorsque j'essaie d'exécuter ce code j'obtiens l'erreur suivante:

Uncaught TypeError: Cannot read property 'tokens' of undefined

N'importe quelle aide ou direction ici serait grandement appréciée. J'ai juste besoin de savoir comment obtenir les données JSON Je travaille avec Typeahead/Bloodhound.

Merci!

17
demandé sur Community 2014-07-03 21:41:12

2 réponses

Vous devez écrire la fonction de filtre de sorte qu'il crée un tableau d'objets javascript à utiliser comme références. Le suivant devrait fonctionner (je n'ai pas testé):

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

(un exemple de la fonction filter peut être trouvé ici)

Et changez votre datumtokenizer:

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

changez aussi votre displaykey en:

displayKey: 'title'

car C'est la clé que Typeahead utilisera pour la recherche.

Comme pour en affichant le nom de la chanson et l'artiste dans la liste des suggestons, je vous suggère d'utiliser le modelage (par exemple le guidon) pour afficher les résultats. Voir l'exemple "Custom Template" dans page des exemples de typographie. Votre balisage de suggestion ressemblera alors à ce qui suit:

suggestion: Handlebars.compile('<p><strong>{{title}}</strong> by {{artistName}}</p>')
18
répondu Ben Smith 2016-01-12 21:41:09

ma réponse n'est pas nouvelle, mais juste une mise à jour pour v0.11 of twitter typeahead. Comme toujours, redirigez vos upvotes (s'il y en a) vers la réponse originale.

un rappel amical à tous ceux qui utilisent encore Twitter-Typeahead est éloigner de ce référentiel n'est plus maintenu. Au lieu de cela, redirigez-vous vers corejavascript / typeahead.js ce qui est une bifurcation du dépôt original, et le même auteur (@JakeHarding) maintient ce référentiel.

de v0.10 à v0.11 quelques choses ont changé, et il en est de même de la réponse. Voici mon nouveau code pour cette nouvelle version.

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'
    });

Ce qui a changé:

  1. Il n'y a pas de filter option sous prefetch. Au lieu de cela, vous devez utiliser transform.
  2. displayKeytypeahead() la fonction a été changée pour simplement display.
  3. cachetransform option est définie à false de sorte que la source de données est chargée à chaque fois. C'est bon pour tester, mais dans le serveur de production, cette option doit être désactivée si la mise en cache des données est nécessaire.

comme note supplémentaire pour les gens qui essaient cet exemple avec différentes sources de données cache mis à true. Vous devez toujours exécuter window.localStorage.clear(); méthode dans votre console pour effacer le déjà présent stockage local de sorte que de nouvelles données peuvent être récupérées. Si vous ne le faites pas, les anciennes données seront utilisées, et vous pourriez pensez pourquoi votre code ne fonctionne pas.

en Voici un qui fonctionne JSFIDDLE exemple pour commencer. Quelques points à noter:

  1. Je ne savais pas s'il y avait un CDN pour typeahead, donc j'ai simplement collé tout le code javascript de typeahead dedans. Au bas de la page, vous pouvez regarder ma fonction.
  2. les points de source des données d'un lien qui est un fichier hébergé dans mon compte dropbox. Dans le cas où je supprimer ce fichier, cet exemple ne fonctionnerait pas du tout. Par conséquent, vous devez fournir votre propre source. Voici le contenu de ce fichier - [{"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
répondu Rash 2016-01-02 21:54:30