2

I am using jQuery autocomplete remote source with caching. As per demo by jQUery UI website javascript of remote source with caching is

<script>
$(function() {
    var cache = {},
        lastXhr;
    $( "#birds" ).autocomplete({
        minLength: 2,
        source: function( request, response ) {
            var term = request.term;
            if ( term in cache ) {
                response( cache[ term ] );
                return;
            }

            lastXhr = $.getJSON( "search.php", request, function( data, status, xhr ) {
                cache[ term ] = data;
                if ( xhr === lastXhr ) {
                    response( data );
                }
            });
        }
    });
});
</script>

Now I want to add some code to above javascript to display image in autocomplete list. There is an excellent example for displaying image in jQuery autocomplete such as: http://jsfiddle.net/3zSMG/ but it does not include caching part.

I have been trying but NOT able to integrate this example into the existing remote with caching javascript. Any help would be very much appreciated. Many thanks.

FOLLOW-UP: As suggested by Andrew Whitaker, I have updated my script as follow:

<script>
$(function() {
    var cache = {},
        lastXhr;
    $( "#birds" ).autocomplete({
        minLength: 2,
        source: function( request, response ) {
            var term = request.term;
            if ( term in cache ) {
                response(cache[term]);
                return;
            }

            lastXhr = $.getJSON( "search.php", request, function( data, status, xhr ) {
                var results;
                if ( xhr === lastXhr ) {
                    results = $.map(data, function(item) {
                        return {
                        value: item.value,
                        avatar: item.avatar
                        };
                    });
                    cache[term] = results;
                    response(results);
                }                   
            });
        },
    }).data("autocomplete")._renderItem = function (ul, item) {
    if ( item.value != null ) {
        if ( item.avatar != null) {
            return $("<li/>")
                .data("item.autocomplete", item)
                .append("<a><img src='images/" + item.avatar + "' />" + item.value + "</a>")
                .appendTo(ul);
            }
        else {
            return $("<li/>")
                .data("item.autocomplete", item)
                .append("<a>" + item.value + "</a>")
                .appendTo(ul);
        }
    }
    }; 
});

And content of search.php:

<?php
require_once "config.php";
$term = trim(strip_tags($_GET['term']));//retrieve the search term that autocomplete sends
$qstring = "select id, subject as value, avatar from Suggests where subject LIKE '%".$term."%'";
$result = mysql_query($qstring);//query the database for entries containing the term
while ($row = mysql_fetch_array($result,MYSQL_ASSOC))//loop through the retrieved values
{
    $row['value']=htmlentities(stripslashes($row['value']));
    $row['id']=(int)$row['id'];
    $row['avatar']=$row['avatar'];
    $row_set[] = $row;//build an array
}
echo json_encode($row_set);//format the array into json data

?>

I am able to see images in autocomplete list. But there is an issue: After keying in few letters, autocomplete list is shown up, if I continue adding some more random letters to expect autcomplete list to disappear (because the userinput no longer matches) but it does not. Andrew's example work well. Is there anything wrong with my javascript? Trying to debug by Firebug, I got error: TypeError element is null.

err

Harry
  • 570
  • 2
  • 10
  • 19

2 Answers2

3

The key to the image portion of the demos is overriding the _renderItem function to change the li's that are generated to suggest items. This usually means that your source is an array with objects that have a label and/or value property, as well as a property that allows you to display the image correctly inside of _renderItem.

The caching code just stores the search term and results in a hash and looks in that hash before hitting the server.

Using the JSFiddle you linked as an example, here's something using StackOverflow's API that does caching and images:

$(document).ready(function() {
    var cache = {},
        lastXhr;

    $("#auto").autocomplete({
        source: function(request, response) {
            var term = request.term;

            if (term in cache) {
                response(cache[term]);
                return;
            }

            lastXhr = $.ajax({
                url: "http://api.stackoverflow.com/1.1/users",
                data: {
                    filter: request.term,
                    pagesize: 10
                },
                jsonp: "jsonp",
                dataType: "jsonp",
                success: function(data, status, xhr) {
                    var results;
                    if (xhr === lastXhr) {
                        results = $.map(data.users, function(el, index) {
                            return {
                                value: el.display_name,
                                avatar: "http://www.gravatar.com/avatar/" + el.email_hash
                            };
                        });

                        cache[term] = results;
                        response(results);                                 
                    }
                }
            });
        },
        delay: 500
    }).data("autocomplete")._renderItem = function(ul, item) {
        return $("<li />")
            .data("item.autocomplete", item)
            .append("<a><img src='" + item.avatar + "' />" + item.value + "</a>")
            .appendTo(ul);
    };
});​

Notes:

  • This example is more complex than the examples on jQueryUI's website because the data from the API has to be transformed (to have avatar/value properties). The important thing to note is that we're caching the received values after the $.map call transforms the result array.
  • This looks complicated but just remember the two guidelines at the top of the answer and you should be good.

Example: http://jsfiddle.net/rK7TS/

Andrew Whitaker
  • 124,656
  • 32
  • 289
  • 307
0

Here's what I did:

    lastXhr = $.getJSON( action, request, function( data, status, xhr ) {

        if( data && data !== null ) {
            var results;
            if( xhr === lastXhr ) {
                results = $.map(data, function(item) {
                    return {
                        value: item.value,
                        avatar: item.avatar
                    };
                });
                cache[term] = results;
                response(results);
            }
        } else {
            response([{ value: 'No results found.', avatar: null}]);
        }

    });
WayneT
  • 176
  • 1
  • 12