2014-10-23 10 views
5

sto lottando per tutto il giorno. La mia espressione di ricerca typeahead funziona perfettamente con dati json remoti. Ma quando provo a utilizzare gli stessi dati JSON dei dati precaricati, il suggerimento è vuoto. Dopo aver colpito il primo segno ottengo il messaggio predefinito "Impossibile trovare qualsiasi cosa ..." per un risultato vuoto.Twitter typeahead nessun risultato quando si usa "prefetch", ma si lavora con "remote" JSON

Ecco il mio script:

function initialTypeaheadTest(){ 
    var mo_selector = $('*[data-moT="mysearch"]'); 
    var engine = new Bloodhound({ 
     limit: 10 
     ,prefetch: {url:'/api/action/getjsontest'} 
     //,remote: {url:'/api/action/getjsontest'} 
     ,datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name') 
     ,queryTokenizer: Bloodhound.tokenizers.whitespace 
    }); 
    engine.clearPrefetchCache(); // only for test purposes 
    engine.initialize(); 

    mo_selector.typeahead(
     { 
      hint: true, 
      highlight: true, 
      minLength: 1 
     }, { 
     name: 'engine', 
     displayKey: 'name', 
     source: engine.ttAdapter(), 
      templates: { 
       empty: [ 
        '<div class="empty-message">', 
        'unable to find anything that match the current query', 
        '</div>' 
       ].join('\n'), 
       suggestion: Handlebars.compile([ 
         '<div id="{{value}}"><p style="max-height:100%;"><strong>{{title}}</strong></p>', 
         '<span style="font-size:12px;">{{year}}</span></div>' 
        ].join('')) 
      } 
    }); 
} 

e questo è il mio JSON:

[{ 
"year":"02 Feb 2013 at 00:40 by anonymous", 
"title":"JavaScript HTML DOM Changing HTML Content", 
"value":"1", 
"tokens":["JavaScript", "HTML", "DOM", "Changing", "HTML", "Content"] 
},{ 
"year":"02 Feb 2013 at 00:42 by anonymous", 
"title":"WDR.de", 
"value":"2", 
"tokens":["WDR.de"] 
},{ 
"year":"02 Feb 2013 at 00:46 by anonymous", 
"title":"Nachrichten, aktuelle Schlagzeilen und Videos - n-tv.de", 
"value":"3", 
"tokens":["Nachrichten", "aktuelle", "Schlagzeilen", "und", "Videos", "n", "tv.de"] 
},{ 
"year":"02 Feb 2013 at 00:55 by anonymous", 
"title":"JavaScript RegExp Object", 
"value":"5", 
"tokens":["JavaScript", "RegExp", "Object"] 
},{ 
"year":"15 Feb 2013 at 23:24 by anonymous", 
"title":"DotnetNuke Module Car Listing Module", 
"value":"8", 
"tokens":["DotnetNuke", "Module", "Car", "Listing", "Module"] 
},{ 
"year":"08 Feb 2014 at 01:08 by advertiser", 
"title":"Empfehlung", 
"value":"1000", 
"tokens":["Empfehlung"] 
}] 

percorso originale: mattopen.com/api/action/getjsontest

per me, tutto sembra buono . I dati JSON sono ben formati. Tutte le stringhe (ad esempio in token) sono citate tra virgolette doppie. Perché i dati remoti funzionano ma non il prefetch?

qualcuno può indicarmi la giusta direzione? grazie

risposta

5

Tutto nella configurazione è buono con l'eccezione del tokenizer impostato. Poiché si sta restituendo un tipo di oggetto json nell'array di dati, è necessario specificare quale proprietà/campo si trova nell'oggetto json che si desidera tokenizzare. Nel codice si specifica name ma il tipo JSON non contiene name. Se si modifica da name a title, tutto funziona come previsto e viene quindi cercato il campo title.

Cambio Linea:

datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name') 

A:

datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title') 

Ciò presuppone il campo che si desidera utilizzare title come indice per la ricerca. Se si preferisce cercare un altro campo/proprietà, cambiarlo con il nome di quel campo/proprietà presente nel tipo di oggetto elencato nella matrice.

Se si desidera utilizzare i gettoni che hai fornito in oggetto si può fare a fornendo una funzione che fa esattamente questo. Sostituire la linea datumTokenizer con questo:

,datumTokenizer: function (yourObj) { 
    return yourObj.tokens; // returns the tokens array in your object 
} 

Tra l'altro il default Bloodhound.tokenizers.obj.whitespace significa che cercherà di dividere una stringa con spazi bianchi. Questo è anche perché non si vede sopra l'ultima realizzazione gettoni come io supporre che il vostro campo tokens avrà sempre stringhe intere che si desidera come è.

Dal Bloodhound Documentation

datumTokenizer - Una funzione con la firma (dato) che trasforma un dato in un array di token di stringa. Necessario.

Ho anche aggiunto sufficient e impostarlo a 1, questo indica al motore che se almeno 1 articolo è restituito (da prefetch in questo caso) poi un viaggio al server non è necessario.

sufficiente - Se il numero di riferimenti forniti dall'indice di ricerca interno è inferiore al necessario, verrà utilizzato il telecomando per eseguire il backfill delle richieste di ricerca attivate chiamando #search. Il valore predefinito è 5.

Inoltre, per testare è possibile creare un file su disco (consente di chiamare prefetchData.json) nella directory principale del sito, copiare il testo dei dati JSON direttamente in questo file che hai elencato nella tua domanda, quindi modificare l'URL per puntare direttamente a esso.

prefetch: {url:'/prefetchData.json'} 

Questo è il codice completo funzionante con le modifiche sopra menzionate. Ora se digiti J dovresti ottenere 2 risultati restituiti.

function initialTypeaheadTest(){ 
    var mo_selector = $('*[data-moT="mysearch"]'); 
    var engine = new Bloodhound({ 
     limit: 10 
     ,sufficient:1 
     ,prefetch: {url:'/prefetchData.json'} 
     //,remote: {url:'/api/action/getjsontest'} // left it commented out to prove it works 
     ,datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title') 
     ,queryTokenizer: Bloodhound.tokenizers.whitespace 
    }); 
    engine.clearPrefetchCache(); // only for test purposes 
    engine.initialize(); 

    mo_selector.typeahead(
     { 
      hint: true, 
      highlight: true, 
      minLength: 1 
     }, { 
     name: 'engine', 
     displayKey: 'name', 
     source: engine.ttAdapter(), 
      templates: { 
       empty: [ 
        '<div class="empty-message">', 
        'unable to find anything that match the current query', 
        '</div>' 
       ].join('\n'), 
       suggestion: Handlebars.compile([ 
         '<div id="{{value}}"><p style="max-height:100%;"><strong>{{title}}</strong></p>', 
         '<span style="font-size:12px;">{{year}}</span></div>' 
        ].join('')) 
      } 
    }); 
} 
Problemi correlati