2014-07-03 6 views
17

UPDATEtypeahead v0.10.2 & Bloodhound - Lavorare con nidificate JSON Oggetti

Sulla base della risposta corretta da @BenSmith (https://stackoverflow.com/users/203371/BenSmith) sono stato in grado di trovare il mio problema e scoperto che non ero la navigazione attraverso il mio JSON gerarchia correttamente. Ecco il codice di lavoro:

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

Grazie @BenSmith per l'aiuto!


domanda iniziale

Sono nuovo di lavorare con typeahead e Bloodhound. La documentazione non è molto utile. Ho un set di oggetti JSON che torno da un'API con cui lavoro. Sto cercando di capire come navigare attraverso i miei oggetti JSON in modo che Bloodhound possa capirli.

L'obiettivo qui è che un utente inizierà a digitare un nome di brano. Il completamento automatico mostrerà quindi un elenco di nomi di brani e l'artista con cui è stato eseguito.

Per esempio: Chimes At Midnight di Mastodon

Sto usando le ultime versioni di ogni libreria: https://twitter.github.io/typeahead.js/

Il campione 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"}]}} 

Utilizzare questo sito http://json.parser.online.fr/ per formattare facilmente il JSON.

Il JSON che tornerò sarà sempre nello stesso formato, ma conterrà dati diversi. In questo esempio, le "tracce" sono nulle. Altri risultati avranno dati. Dovrei anche essere in grado di accedere a tali dati.

Sto usando l'ultima versione di JQuery. Ecco quello che ho incluso nel mio pagina html:

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

Ecco il codice HTML:

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

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

Quando provo a eseguire questo codice ho ottiene il seguente errore:

Tipo non rilevato Errore: impossibile leggere i "token" di proprietà di un definito

Qualsiasi aiuto o direzione qui sarebbe molto apprezzato. Ho solo bisogno di sapere come ottenere i dati JSON con cui lavoro con Typeahead/Bloodhound.

Grazie!

+0

Contento di poter aiutare Jared :) –

risposta

18

È necessario scrivere la funzione filtro in modo da creare una serie di oggetti javascript da utilizzare come datum.Quanto segue dovrebbe funzionare (non ho ancora testato questo):

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

(un esempio della funzione di filtro può essere trovato here)

e cambiare il tuo datumtokenizer a:

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

anche cambia il tuo displaykey a:

displayKey: 'title' 

Poiché questa è la chiave che Typeahead wi Userò per la ricerca.

Per quanto riguarda la visualizzazione del nome del brano e dell'artista nell'elenco dei suggerimenti, suggerisco di utilizzare i modelli (ad esempio Handlebars) per la visualizzazione dei risultati. Vedere l'esempio "Modello personalizzato" in Typeahead's examples page. Il tuo suggerimento mark-up sarà poi un aspetto simile al seguente:

suggestion: Handlebars.compile('<p><strong>{{title}}</strong> by {{artistName}}</p>') 
+0

Ciao, grazie mille per questa risposta molto ben fatta!Mi ha davvero aiutato a capirlo meglio. Ho implementato il codice e non ci sono più errori. Ho ancora un problema però. Quando provo a cercare il nome di un brano, compare il mio messaggio modello "vuoto". Per qualche motivo non è in grado di trovare i nomi dei brani quando li digito. Per semplificare, ho creato un JSFiddle qui: http://jsfiddle.net/VBLTS/2/ – Jared

+0

Ho dimenticato di menzionarlo. Ottengo questo errore JS: Uncaught TypeError: Impossibile leggere la proprietà 'length' di undefined – Jared

+1

Ho trovato il problema. Non stavo navigando correttamente nel JSON. Stavo chiamando response.songs, quando davvero doveva essere response.response.songs basato sulla mia struttura JSON. Così ho rinominato la funzione in dati e ora richiamo dati.response.songs e tutto funziona. – Jared

10

La mia risposta è nulla di nuovo, ma solo un aggiornamento per v0.11 di Twitter typeahead. Come sempre, reindirizza i tuoi upvotes (se ce ne sono) alla risposta originale.

A friendly reminder to everyone who are still using Twitter-Typeahead is to move away from this repository as it is no longer maintained. Instead redirect yourself to corejavascript/typeahead.js which is a fork of the original repository, and the same author (@JakeHarding) maintains this repository.

Dalla v0.10 alla v0.11 alcune cose sono cambiate, e quindi deve essere la risposta. Ecco il mio nuovo codice per questa versione più recente.

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

Cosa è cambiato:

  1. Non v'è alcuna opzione filter sotto prefetch. Invece devi usare transform.
  2. displayKey nella funzione typeahead() è stato modificato in display.
  3. cache sotto transform l'opzione è impostata su false in modo che l'origine dati venga caricata ogni volta. Questo è utile per i test, ma nel server di produzione, questa opzione deve essere disabilitata se è richiesta la memorizzazione nella cache dei dati.

As an additional note to folks who are trying this example with different data sources with cache set to true. You must always run window.localStorage.clear(); method in your console to clear the already present local storage so that new data can be retrieved. Failing to do so will result in the old data being used, and you might think why your code is not working.

Ecco un lavoro JSFIDDLE esempio per iniziare. Alcuni punti da notare:

  1. Non sapevo se c'è un CDN per typeahead, quindi ho semplicemente incollato l'intero codice javascript typeahead lì. In fondo alla pagina, puoi guardare la mia funzione.
  2. L'origine dati punta a un collegamento che è un file ospitato nel mio account casella personale. Nel caso rimuovo questo file, questo esempio non funzionerebbe affatto. Quindi è necessario fornire la propria fonte. Ecco il contenuto di quel file - [{"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"}]
+0

Bel aggiornamento Rash, e grazie per avermi informato su corejavascript/typeahead.js! –

Problemi correlati