Search code examples
javascriptjqueryjsonjquery-ui-autocompletegoogle-books

Google books jquery autocomplete from api url call json not working


I have a search box, findBook, and I'm trying to use the jquery autocomplete with json api call to google-books api to display book title, author and thumbnail.

When I type in the search box nothing happens. Any help would be appreciated. The source for the autocomplete is the google-boosk api url. Thanks :)

<!DOCTYPE html>
<html>
<head>

<!-- Your web-app is https, so your scripts need to be too -->


<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<link rel="stylesheet" href="/style.css" type="text/css">
<link rel="stylesheet" href="/home.css" type="text/css">

<script src='https://code.jquery.com/jquery-2.2.4.js'
        integrity="sha256-gvQgAFzTH6trSrAWoH1iPo9Xc96QxSZ3feW6kem+O00="
        crossorigin="anonymous"></script>

<script src='https://code.jquery.com/ui/1.12.0/jquery-ui.js'></script>
<link href="https://code.jquery.com/ui/1.12.0/themes/base/jquery-ui.css" rel="stylesheet" media="screen" />
<script type='text/javascript'>

</script>

<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js'></script>

<script type="text/javascript">
    $(document).ready(function(){

        $("#findBook").autocomplete({
            source: function (request, response) {

                $.ajax({
                    method:"GET",
                    dataType: "json",
                    url: "https://www.googleapis.com/books/v1/volumes?q=" + request.term,


                    success: function (data) {
                        console.log(data);
                        var transformed = $.map(data.items.volumeInfo, function (book) {
                            return {
                                title: book.title,
                                author: book.author,
                                image: book.imageLinks.thumbnail
                            };
                        });

                        response(transformed);
                    },

                    error: function () {

                        response([]);
                    }
                });
            }

        });
    });

 </script>


</head>
<body>


 <div class="searchBook">



   <input type="text" placeholder="Search.." id="findBook" />


</div>



  </body>

</html>

Solution

  • $.map() jQuery function requires an array to iterate. In your case: data.items.volumeInfo is undefined.

    However, you can use Array#map JavaScript function to iterate over data.items, in this way:

    var transformed = data.items.map(function(book) {
      return {
        title: book.volumeInfo.title,
        author: book.volumeInfo.authors,
        image: book.volumeInfo.imageLinks.thumbnail
      };
    });
    

    In the above code, the book object has a volumeInfo attribute, so yo can access its attributes to build a new object, in this case transformed variable.

    Now, to show the book title, author and the thumbnail, you will have to modify the rendered HTML of jQuery autocomplete plugin, using the _renderItem function.

    Something like this function:

    .autocomplete("instance")._renderItem = function(ul, item) {
      return $("<li></li>")
        .data("item.autocomplete", item)
        .append("<a>" + "<img src=\"" + item.image + "\" style=\"height: 40%;\" /><br />" + (item.author && item.author.length ? item.author.map(function(x) {
          return x;
        }).join(" | ") : '') + " - " + item.title + "</a>")
        .appendTo(ul);
    };
    

    Getting this result:

    enter image description here

    See in this example:

    $(function() {
    
      $("#findBook").autocomplete({
        source: function(request, response) {
          $.ajax({
            url: "https://www.googleapis.com/books/v1/volumes?q=" + request.term,
            dataType: "json",
            data: {
              term: request.term
            },
            success: function(data) {
              var transformed = data.items.map(function(book) {
                return {
                  title: book.volumeInfo.title,
                  author: book.volumeInfo.authors,
                  image: book.volumeInfo.imageLinks.thumbnail
                };
              });
              response(transformed);
            }
          });
        }
      }).autocomplete("instance")._renderItem = function(ul, item) {
        return $("<li></li>")
          .data("item.autocomplete", item)
          .append("<a>" + "<img src=\"" + item.image + "\" style=\"height: 40%;\" /><br />" + (item.author && item.author.length ? item.author.map(function(x) {
            return x;
          }).join(" | ") : '') + " - " + item.title + "</a>")
          .appendTo(ul);
      };
    });
    <!doctype html>
    <html lang="en">
    
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>jQuery UI Autocomplete - Remote JSONP datasource</title>
      <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
      <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
      <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    </head>
    
    <body>
      <div class="searchBook">
        <input type="text" placeholder="Search..." id="findBook">
      </div>
    </body>
    
    </html>

    Remember to avoid mixing different versions of the jQuery library.

    Update: To show only the image.

    The options are rendered by default, if they have text to display. However, we can add a hidden span with the text, where it would only be showing the image.

    Something like in this example:

    $(function() {
    
      $("#findBook").autocomplete({
        source: function(request, response) {
          $.ajax({
            url: "https://www.googleapis.com/books/v1/volumes?q=" + request.term,
            dataType: "json",
            data: {
              term: request.term
            },
            success: function(data) {
              var transformed = data.items.map(function(book) {
                return {
                  title: book.volumeInfo.title,
                  author: book.volumeInfo.authors,
                  image: book.volumeInfo.imageLinks.thumbnail
                };
              });
              response(transformed);
            }
          });
        }
      }).autocomplete("instance")._renderItem = function(ul, item) {
        return $("<li></li>")
          .data("item.autocomplete", item)
          .append("<img src=\"" + item.image + "\" style=\"height: 40%;\" /><span hidden>" + item.image + "</span>")
          .appendTo(ul);
      };
    });
    <!doctype html>
    <html lang="en">
    
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>jQuery UI Autocomplete - Remote JSONP datasource</title>
      <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
      <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
      <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    </head>
    
    <body>
      <div class="searchBook">
        <input type="text" placeholder="Search..." id="findBook">
      </div>
    </body>
    
    </html>

    Hope this helps!