Daniel Semel
Daniel Semel

Reputation: 185

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>

Upvotes: 1

Views: 811

Answers (2)

$.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!

Upvotes: 1

Quethzel Diaz
Quethzel Diaz

Reputation: 641

You are loading two diferents jQuery versions jquery-2.2.4 and jquery/3.3.1/jquery.js and the version 3 it's loading after the jquery UI. Thats the issue.

I Just remove the jquery-2x and move the jquery3x before the jquery UI. In fact should be work if you just move the jquery-3x before the jquery-UI whitout removing anything.

<!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://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js'></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">
    $(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>

example here

Upvotes: 0

Related Questions