1

I have a site with stocks. I would like to add typeahead functionality to my bootstrap template. Since there are about 5000 stocks and will be even more in the future. I am using haystack with whoosh index. I should be using remote version of typeahead.js, but it is not working. Could you please take a look and tell me what am I missing?

    <script type="text/javascript">
    var stocks = new Bloodhound({
        datumTokenizer: function (datum) {
            return Bloodhound.tokenizers.whitespace(datum.name);
        },
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        limit: 5,
        remote: {
            url: "/search/autocomplete/",
            replace: function(url, query) {
                return url + "?q=" + query;
            },
            filter: function(stocks) {
                return $.map(stocks, function(data) {
                    return {
                        tokens: data.tokens,
                        symbol: data.symbol,
                        name: data.name
                    }
                });
            }
        }
    });
    stocks.initialize();
    $('.typeahead').typeahead(null, {
            name: 'stocks',
            displayKey: 'name',
            minLength: 1, // send AJAX request only after user type in at least X characters
            source: stocks.ttAdapter()
        });
</script>

This is my form

<form class="input-prepend" method="get" action="/search/">
    <div id="remote">
        <button type="submit" class="btn">Search</button>
        <input type="text" class="typeahead" id="id_q" placeholder="Stock symbol or name" autocomplete="off" name="q">
    </div>
</form>

Urls.py

url(r'^search/autocomplete/', 'stocks.views.autocomplete'),
url(r'^search/', include('haystack.urls')),

autocomplete view

from haystack.query import SearchQuerySet
import json
def autocomplete(request):
    sqs = SearchQuerySet().autocomplete(content_auto=request.GET.get('q', ''))[:5]
    array = []
    for result in sqs:
        data = {"symbol": str(result.symbol),
                 "name": str(result.name),
                 "tokens": str(result.name).split()}
        array.insert(0, data)
    return HttpResponse(json.dumps(array), content_type='application/json')

json response:

[{"tokens": ["Arbor", "Realty", "Trus"], "symbol": "ABR", "name": "Arbor Realty Trus"}, {"tokens": ["ABM", "Industries", "In"], "symbol": "ABM", "name": "ABM Industries In"}, {"tokens": ["AmerisourceBergen"], "symbol": "ABC", "name": "AmerisourceBergen"}, {"tokens": ["ABB", "Ltd", "Common", "St"], "symbol": "ABB", "name": "ABB Ltd Common St"}, {"tokens": ["Allianceberstein"], "symbol": "AB", "name": "Allianceberstein "}]

This is my domain name: digrin.com and this is autocomplete url. What am I missing?

Lucas03
  • 2,267
  • 2
  • 32
  • 60
  • Do you get any errors in your browser console? – Ben Smith Jan 19 '15 at 17:33
  • I get warnings. I am not very used to coding in js (i did not check console yet). These are the warnings. http://pastebin.com/F7u5S6QN You can check my code on digrin.com yourself. – Lucas03 Jan 19 '15 at 17:45

1 Answers1

2

I can see two problems:

1) Your script declaration is missing a type attribute:

<script src="http://code.jquery.com/jquery-1.11.0.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.js"></script>
<script type='text/javascript' src="http://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"></script>

add "type='text/javascript'" to the script declarations for jquery and bootstrap.

A more modern way of declaring your script tags can be found here.

2) To initialise Typeahead you need to place the code into your jQuery ready method i.e.

$(function(){
 var stocks = new Bloodhound({
    datumTokenizer: function (datum) {
        return Bloodhound.tokenizers.whitespace(datum.name);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    limit: 5,
    remote: {
        url: "/search/autocomplete/",
        replace: function(url, query) {
            return url + "?q=" + query;
        },
        filter: function(stocks) {
            return $.map(stocks, function(data) {
                return {
                    tokens: data.tokens,
                    symbol: data.symbol,
                    name: data.name
                }
            });
        }
    }
});
stocks.initialize();
$('.typeahead').typeahead(null, {
        name: 'stocks',
        displayKey: 'name',
        minLength: 1, // send AJAX request only after user type in at least X characters
        source: stocks.ttAdapter()
    }); 
});

As it is currently the typeahead code wont get loaded.

Community
  • 1
  • 1
Ben Smith
  • 19,589
  • 6
  • 65
  • 93
  • Thanks for your answer. I added async/defer and type to js libraries(should I add one for typeahead initialization too?). (thanks for informative link, I did not know) Also copied your code to initialize Typeahead. It still doesn't work (updated online version as well). May be you could test it on your jsfiddle? http://jsfiddle.net/Fresh/UkB7u/ – Lucas03 Jan 19 '15 at 22:16
  • The reference to jQuery is still not working. Your script tags are now missing "http://", in your code they only read "//". – Ben Smith Jan 19 '15 at 22:42
  • It doesnt work with http either. Its just relative url - http://stackoverflow.com/questions/550038/is-it-valid-to-replace-http-with-in-a-script-src-http – Lucas03 Jan 19 '15 at 23:02
  • nice, wasnt aware that you could drop the http. As a test, try getting rid of the "defer" on the jquery declaration, it could be that which is causing this odd error. We'll get there in the end! – Ben Smith Jan 19 '15 at 23:25
  • Well, it partly works. 1. When it is active, text is not visible. It does it with used typeahead.css and without it as well. Any idea how to fix this? I guess it's css. 2. It only searches on symbol. Can you by any chance point me to docs or article how to search on more fields (tokens or name)? 3. I need to redirect to stock profile when suggestion is selected, but I guess I can do this reading docs more carefully by myself. Thanks again for your help! – Lucas03 Jan 19 '15 at 23:49
  • Glad I could help @Lucas03. As I found the original issue could you mark this as answered? What you are asking in the above comment is in fact a different issue, which would be valuable to the community in a separate SO question. – Ben Smith Jan 20 '15 at 00:01