Google Books APIsを、JavaScriptを使ってGoogleブックスから本を検索できるスニペットを作ってみました。
サンプルもあるので触ってみてください。
Google Books APIsとは?
Google Books APIsは、「Google ブックス」から好みのキーワードを指定して本を検索することができるAPIです。
同じようなAPIで、Web検索ができる「Google検索」は一定量の使用で有料で、かつAPIトークンの取得が必要だったりしますが、この「Google Books APIs」はトークン取得も不要、かつ無料で使えます。
この記事では、そんな「Google Books APIs」を使った検索を実装しています。
Google Books APIsを使った検索サンプル
早速Google Books APIsを使ったサンプルです。
テキストフィールドに検索したいキーワードを入力し、「検索」のボタンを押すことで10件検索結果が表示されます。
再び検索する場合は、「クリア」ボタンを選択してから検索するようにしてください。
クリアを選択すると、検索結果とキーワードがリセットされます。
サンプルのコード
コードはHTML・JavaScript・CSSの3種類です。順に解説していきます。
HTML
HTMLは、主に検索で使用する「search」のclassがついた要素と、検索結果を出力させる「books」のidがついた要素の2つです。
<div class="search">
<input id="inputField" type="text" placeholder="Google ブックスから検索">
<button id="ajaxButton"><i class="fas fa-search"></i> 検索</button>
<button id="clearButton">クリア</button>
</div>
<ul id="books">
</ul>
「検索」の要素の中には、テキストを打ち込むテキストフィールドと、結果を表示させる検索ボタンと、クリアのボタンを入れています。
JavaScript
JavaScriptは以下のように記述量が多めで、大きく分けて冒頭にある「Google Books APIs」と、「ボタン」の有効・無効を切り替える2種類です。
(function () {
var httpRequest;
document.getElementById("ajaxButton").addEventListener('click', makeRequest);
function makeRequest() {
var userInput = document.getElementById('inputField').value;
var query = userInput.split(' ').join('+');
httpRequest = new XMLHttpRequest();
if (!httpRequest) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
httpRequest.onreadystatechange = alertContents;
httpRequest.open('GET', `https://www.googleapis.com/books/v1/volumes?q=${query}`);
httpRequest.send();
}
function alertContents() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
var obj = httpRequest.responseText;
var parsed = JSON.parse(obj); //ループのオブジェクト
for (i = 0; i < parsed.items.length; i++) {
var ul = document.getElementById('books'); //APIで出力させる要素
if(typeof parsed.items[i].volumeInfo.imageLinks === "undefined"){
var li = document.createElement('li');
li.innerHTML = "<a class='bookLink' href='" + parsed.items[i].volumeInfo.previewLink + "' target='_blank' rel='noopener noreferrer'><div class='bookImage'><div class='bookImageInner'><img src='https://dubdesign.net/wp-content/uploads/2022/03/noimage.jpg' alt='" + parsed.items[i].volumeInfo.title + "'></div></div><p class='bookPublishedDate'>" + parsed.items[i].volumeInfo.publishedDate + "</p><p class='bookTitle'>" + parsed.items[i].volumeInfo.title + "</p></a>" ;
ul.appendChild(li);}
else {
var li = document.createElement('li');
li.innerHTML = "<a class='bookLink' href='" + parsed.items[i].volumeInfo.previewLink + "' target='_blank' rel='noopener noreferrer'><div class='bookImage'><div class='bookImageInner'><img src='" + parsed.items[i].volumeInfo.imageLinks.thumbnail + "' alt='" + parsed.items[i].volumeInfo.title + "'></div></div><p class='bookPublishedDate'>" + parsed.items[i].volumeInfo.publishedDate + "</p><p class='bookTitle'>" + parsed.items[i].volumeInfo.title + "</p></a>" ;
ul.appendChild(li);};
}
} else {
console.log('There was a problem with the request.');
}
}
}
})();
// ボタンクリックで無効化
document.getElementById("ajaxButton").addEventListener('click', () => {
const btn = document.getElementById("ajaxButton");
btn.disabled=true;
});
// クリアで検索有効化
document.getElementById("clearButton").addEventListener('click', () => {
const btn = document.getElementById("ajaxButton");
btn.disabled=false;
// 検索結果を消す
const ul = document.getElementById("books");
const len = ul.children.length ;
for ( var i = 0 ; i < len ; i ++ ) {
ul.removeChild ( ul.children [ 0 ] ) ;}
// 検索のフィールドを消す
const textareaForm = document.getElementById("inputField");
textareaForm.value = '';
});
APIで取得するデータには「書影」にあたる画像があったり・なかったりの有無があるので、for
文を使い条件分岐をさせ、書影がない場合はダミーの画像を表示させるようにしています。
このスニペットをコピペして使う場合は、ダミー画像は変更してくださいませ。
CSS
CSSは、検索結果で出力される要素を整えるプロパティが多く、レイアウトはFlexboxです。
.search #inputField {
background: #FFF;
border: solid 1px #eee;
padding-left: 15px;
padding-right: 15px;
}
/* 検索結果 */
ul#books {
padding: 0;
list-style: none;
border: none;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
gap: 10px;
}
ul#books:after {
content: "";
width: 22%;
}
ul#books li {
width: 22%;
}
a.bookLink {
cursor: pointer;
transition: 0.2s ease-in-out;
display: flex;
flex-direction: column;
text-decoration: none;
color: #313131;
}
.bookImage {
display: flex;
align-items: center;
height: 200px;
margin-bottom: 10px;
}
.bookImageInner {
display: block;
margin: 0 auto;
position: relative;
box-shadow: -6px 6px 10px -2px #001b4440, 0 0 3px #8f9aaf1a;
border-radius: 3px;
transition: 0.3s ease-in-out;
}
.bookImageInner img {
max-height: 190px;
}
a.bookLink:hover > .bookImage .bookImageInner {
transform: scale(1.05);
}
.bookImageInner:after {
bottom: 0;
content: "";
height: 100%;
left: 0;
position: absolute;
width: 100%;
border-radius: 5px;
background: linear-gradient(-90deg,#fff0,#ffffff1a 80%,#ffffff4d 95%,#fff6 96.5%,#cbcbcb14 98%,#6a6a6a1a);
border-radius: 3px;
}
p.bookPublishedDate, p.bookTitle {
margin: 0 auto;
display: block;
padding-left: 10px;
padding-right: 10px;
line-height: 1.4;
}
p.bookPublishedDate {
color: #707070;
font-size: 0.9rem;
position: relative;
margin-bottom: 8px;
}
p.bookPublishedDate:before {
content: "\f017";
font-family: "Font Awesome 5 Free";
font-weight: 100;
font-size: 0.85rem;
margin-right: 5px;
color: #707070;
}
a.bookLink:hover > p.bookTitle {
color: #3a9eff;
}
/* ボタン2度押し */
button#ajaxButton:disabled {
pointer-events: none;
background: #eee;
filter: none;
color: #999;
}
@media screen and (max-width: 767px) {
/* (ここにモバイル用スタイルを記述) */
ul#books li {
width: 41%;
}
}
検索と発行日に使っているアイコンは「Fontawesome」を使っているので、そのまま使う場合はFontawesome本体も読み込むようにしてください。
さいごに
この記事のスニペットは以下の記事を参考にさせて頂きました。
参考 JavaScript で Google Books APIs 使って本を検索して結果一覧を表示するツールを作ってみたzenn.dev詳しい解説もあるので、あわせて参考にしてみてください。