Search code examples
jqueryjsontwitter-bootstraptypeahead.jsbootstrap-typeahead

Update JSON on every keyup for twitter typeahead


I have a html page with an input field. Every time something is typed in this field, there is a call done to a php script with jQuery.

This php script returns a JSON with the results of a particular query based on the input field.

This works fine and I am logging the output in console.

<html>
    <head>
    <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
    <script>
        var r = jQuery(function($) {
            $('#name').keyup(function() {
                var input = $('#name').val();

                var response = $.getJSON('get_names.php', {input: input});

                response.done(function (names) {
                    console.log(names);
                });
            });
        });
    </script>

    </head>

    <body>
        <div><input id="name"></div>
    </body>
</html>

The problem now is that instead of logging to console, I need to merge this with the twitter bootstrap - first example in typeahead.js, so that the json used (states in the below code) is calculated every time by the php script with the content of the field.

$(document).ready(function() {

    var substringMatcher = function(strs) {
    return function findMatches(q, cb) {
        var matches, substringRegex;

        // an array that will be populated with substring matches
        matches = [];

        // regex used to determine if a string contains the substring `q`
        substrRegex = new RegExp(q, 'i');

        // iterate through the pool of strings and for any string that
        // contains the substring `q`, add it to the `matches` array
        $.each(strs, function(i, str) {
        if (substrRegex.test(str)) {
            // the typeahead jQuery plugin expects suggestions to a
            // JavaScript object, refer to typeahead docs for more info
            matches.push({ value: str });
        }
        });

        cb(matches);
    };
    };

    var states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California',
        'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii',
        'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana',
        'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota',
        'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire',
        'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota',
        'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island',
        'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont',
        'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'
    ];

    $('#the-basics .typeahead').typeahead({
        hint: true,
        highlight: true,
        minLength: 1
    },
    {
        name: 'states',
        displayKey: 'value',
        source: substringMatcher(states)
    });
});

I have been trying to catch the value with this but nothing changes:

jQuery(function($) {
    $('#name').keyup(function() {
        var input = $('#name').val();

        names = $.getJSON('get_names.php', {input: input});

    });
});

So: how can I make the JSON be updated every time a keyup event happens, by calling the php script with the input that is written so far?


Solution

  • What I ended up doing is to use Bloodhound and, specifically, replace to create an appropriate query:

    var states = new Bloodhound({
        ...
        remote: {
                url: 'suggest.php?input=',
                replace: function (url, query) {
                        suggestion.input = query;
                        return url + suggestion.input;
                },
                ...
        }
    });
    states.initialize();
    

    All together, the full code looks like this:

    $(function(){
    
            var suggestion = {
                    input: '',
                    normalized: ''
            };
            var states = new Bloodhound({
                    datumTokenizer: function (d){
    
                    },
                    queryTokenizer: Bloodhound.tokenizers.whitespace,
                    remote: {
                            url: 'get_names.php?input=',
                            replace: function (url, query) {
                                    suggestion.input = query;
                                    return url + suggestion.input;
                            },
                            filter: function (data) {
                                    return $.map(data, function(company) { return { value: company }; });
                                    }
                    }
            });
            states.initialize();
    
            $('#the-basics .typeahead').typeahead({
                    minLength: 1,
                    highlight: true
                    },{
                    displayKey: 'value',
                    source: states.ttAdapter()
            });
    });