楽天ブックスAPIを使用した図書検索アプリ：jQuery

### 概要
楽天ブックスAPIを利用した図書検索アプリ（非同期通信）
フロントエンドのみ

```HTML
<div class="wrap">
        <div class="container">
            <div class="header">
                <p class="header__title">Search Books!</p>
            </div>
            <div class="search">
                <div class="search__text">
                    <input type="text" id="js-search-word" class="search__text__input" value="" placeholder="検索する">
                </div>
                <button id="js-search-button" class="search__btn">検索する</button>
            </div>
            <ul class="lists">
                
            </ul>
        </div>
    </div>
```

```CSS
@charset "UTF-8";

html {
    height: 100%;
}
body {
    min-height: 100%;
    color: #333;
    background-color: #fafafa;
}
.container {
}
.header {
    width: 100%;
    background-color: #43cee0;
}
.header__title {
    line-height: 60px;
    text-align: center;
    font-size: 20px;
    color: #fff;
}
.search {
    overflow: hidden;
    margin-bottom: 50px;
    background: #fff;
    box-shadow: 0 1px 5px #ccc;
}
.search__text {
    width: 100%;
}
.search__text__input {
    -webkit-box-sizing: border-box;
            box-sizing: border-box;
    width: 100%;
    margin-bottom: 20px;
    padding: 0 10px;
    line-height: 3em;
    border-top: none;
    border-left: none;
    border-right: none;
    border-bottom: 1px solid #eee;
    font-size: 20px;
}
.search__btn {
    display: block;
    margin: 0 auto 20px;
    padding: 0 20px;
    line-height: 40px;
    border: none;
    font-size: 18px;
    color: #fff;
    background-color: #43cee0;
}
.search__btn:hover {
    background-color: #1eabbd;
}
.lists {
    overflow: hidden;
    margin-left: 20px;
    
}
.lists__item {
    -webkit-box-sizing: border-box;
            box-sizing: border-box;
    display: inline-block;
    width: 25%;
    padding: 0 20px 20px 0;
    vertical-align: top;
    text-align: center;
}
.lists__item__inner {
    width: 100%;
    max-width: 200px;
    margin: 0 auto;
}
.lists__item__link {
    display: block;
    text-decoration: none;
}
.lists__item__img {
    margin-bottom: 20px;
    width: 100%;
    max-width: 150px;
    -webkit-box-shadow: 0 1px 5px #ccc;
            box-shadow: 0 1px 5px #ccc;
}
.lists__item__detail {
    margin-bottom: 10px;
    padding-left: 5em;
    text-indent: -5em;
    line-height: 1.5em;
    text-align: left;
    font-size: 12px;
}
.message {
    margin-bottom: 50px;
    text-align: center;
}

@media screen and (max-width: 767px) {
    .lists__item {
        width: 33.33%;
    }
}

@media screen and (max-width: 479px) {
    .lists__item {
        width: 50%;
    }
}
```

下記からはjqueryの記述となり備忘録として分割して記述ごとに説明を記述していく

```javascript
$(function() {
        var pageNum = 0;
        var prevWord = "";
        $("#js-search-button").on("click", function() {
            pageNum = pageNum+1
            var keyWord = $("#js-search-word").val();
            if(prevWord !== keyWord){
                pageNum = 1;
                $(".lists").empty();
                prevWord = keyWord;
            };
```

上記ではグローバル変数の宣言と検索された時最初に行われる処理について記述している。
グローバル変数pageNumは後ほど出てくるAPIから取得できるpage情報に指定する変数であり、
検索ボタンがクリックされるたびに1をプラスしていく。
変数keyWordには検索欄に入力された値が代入され、下のif文の記述で使用される。
1回目のクリックではprevWordは空のため、keyWordoの値とは一致しないためtrueが返り
処理が実行される。
2回目のクリックの際に違うキーワードで検索した場合のための記述であり、1回目と2回目の
検索ワードは不一致となるため、if文内の処理が実行された結果、emptyにより1回目の検索結果は
削除され、2回目の検索結果が表示されるようになる。

```javascript
            $.ajax({
                type: "GET",
                url: "https://app.rakuten.co.jp/services/api/BooksTotal/Search/20170404",
                data: {
                    applicationId: "1053309271580885189",
                    keyword: keyWord,
                    format: "json",
                    bookGenreId: "001",
                    page: pageNum,
                    hits: 20,
                }
```

上記はAPIを連携させるための記述であり、ajaxは非同期通信を実行するための記述で、対象URLから
getメソッドによりデータを取得する。
data以下にはAPIを使用するためのアプリケーションID、データを落としてくる際のフォーマット、
検索キーワード、など必要な情報を記述する。

```javascript
            }).done(function(data) {
                if (data.count > 0) {
                    $(".comment").remove();
                    var list = "";
                    for (var i=0; i<data.Items.length; i++) {
                            list += `<li class=lists__item>` +
                            `<div class=lists__item__inner>` +
                            `<a href=${data.Items[i].Item.itemUrl} class=lists__item__link target=_blank>` +
                            `<img src=${data.Items[i].Item.largeImageUrl} class=lists__item__img alt>` +
                            `<p class=lists__item__detail>作品名：　${data.Items[i].Item.title}</p>` +
                            `<p class=lists__item__detail>作者　：　${data.Items[i].Item.author}</p>` +
                            `<p class=lists__item__detail>出版社：　${data.Items[i].Item.publisherName}</p>` + `</a>` +
                            `</div>` + `</li>`;
                    };
                    $(".lists").prepend(list);
                } else {
                    $(".comment").remove();
                    $(".lists").before("<div class='comment'></div>");
                    $(".comment").html("<p class='message'>検索結果が見つかりませんでした。<br>別のキーワードで検索して下さい。</p>");
                };
            });
        });
    });
```

done以下では引数にdataを使用し、上述しているdataで取得した情報を使用できるようにしている。
if文によって取得したdataの数が０より多かった場合は変数listにビューに表示させるためのHTMLを
格納し、ul要素の末尾に挿入する。
for文の記述により取得したデータの数だけ処理が繰り返されるため、取得したデータ文の本の情報が
HTMLに変換されビューに表示される。

取得したdataの数が０未満だった場合は検索結果がヒットしなかったということになるので、
エラー文HTMLとしてをul要素の前に挿入しビューに表示させる。