Chrome拡張機能でオートコンプリート付き検索でスプレッドシートから情報を引っ張る方法②

[Chrome拡張機能でオートコンプリート付き検索でスプレッドシートから情報を引っ張る方法①](https://qiita.com/plumfield56/items/c0fbafd8df400688213c)を見ていない方は是非見てください。

前回では認証なしでスプレッドシートからオートコンプリートを実装しましたが、
今回は認証ありで実装していきます。

そのための前提知識として[Chrome拡張機能でスプレッドシート操作する方法](https://qiita.com/plumfield56/items/6fe255180739ba4b1a25)を確認しておいてください。

上記2記事を理解している前提でコードを書いていきます。


# フォルダ構造

フォルダの作りは前回と変わりないです。

```:フォルダ
フォルダ
  ├ manifest.json
  ├ popup.html
  ├ picture.png
  ├ js(フォルダ)
  │   ├ jquery-3.5.1.min.js ※JQuery
  │   ├ jquery-ui.min.js ※JQuery UI
  │   └ popup.js
  │
  └ css(フォルダ)
      ├ jquery-ui.theme.min.css ※JQuery UI
      └ style.css
```


# manifest.json

前の記事と違い `oauth2`, `permissions` の設定が増えています。

```:manifest.json
{
  "name": "スプレッドシートからの情報取得",
  "version": "1.0",
  "manifest_version": 2,
  "description": "スプレッドシートからの情報取得ための拡張機能",
  "key": "{Developer Dashboardに登録ときに作成されるPUBLIC KEY}",
  "content_security_policy": "script-src 'self' https://apis.google.com/; object-src 'self'",
  
  "browser_action":{
    "default_icon": "picture.png",
    "defalt_title": "title",
    "default_popup": "popup.html"
  },
  "oauth2": {
    "client_id": "{GCPでOAuthを作成したときに発行されるID}",
    "scopes":[
      "https://www.googleapis.com/auth/spreadsheets"
    ]
  },
  "permissions": [
    "identity"
  ]
}
```


# popup.html

gapiを使用するための一行が増えています。
<script src="https://apis.google.com/js/client.js?onload=onGAPILoad"></script>


```html:popup.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <!-- cssの読み込み -->
  <link type="text/css" href="css/style.css" rel="stylesheet" />
  <link type="text/css" href="css/jquery-ui.theme.min.css" rel="stylesheet" />
</head>

<body style="min-width: 300px;">
  <div class="text">▼検索したい名前を入力</div>
  <input type="text" id="input">
  <button id="btn">データ取得</button>
  <div class="text" id="displayText"></div>

  <script src="js/jquery-3.5.1.min.js"></script>
  <script src="js/jquery-ui.min.js"></script>
  <script src="https://apis.google.com/js/client.js?onload=onGAPILoad"></script>
  <script src="js/popup.js"></script>

</body>
</html>
```

# popup.js

前の記事でも書いていますが、
SPREADSHEET_TAB_NAMEは日本語が入ると動かないので注意ください。

```javascript:popup.js
const API_KEY = '{GCPで作成したAPI KEY}';
const DISCOVERY_DOCS = ["https://sheets.googleapis.com/$discovery/rest?version=v4"];
const SPREADSHEET_ID = '{スプレッドシートのID}';
const SPREADSHEET_TAB_NAME = '{シート名 or レンジ}';

// jqueryのデータやgapiなどの読み込みが終わってから実行するのにtimeoutを使用
setTimeout(setAutoComplete, 100);

// スプレッドシートの全データを入れるために変数を用意
let values;

// 認証作業 + オートコンプリートの実装
function setAutoComplete() {
  console.log('background');

  gapi.client.init({
    apiKey: API_KEY,
    discoveryDocs: DISCOVERY_DOCS,
  }).then(function () {
    console.log('gapi initialized')
    chrome.identity.getAuthToken({interactive: true}, function(token) {
      console.log(token);
      gapi.auth.setToken({
        'access_token': token,
      });

      // ここからオートコンプリートの実装
      //A2:Aを1次元配列にして指定
      gapi.client.sheets.spreadsheets.values.get({
        spreadsheetId: SPREADSHEET_ID,
        range: SPREADSHEET_TAB_NAME + '!A2:A',
      }).then(function(response) {
        $('#input').autocomplete({
            source: response.result.values.flat()
        })
      });

      // 全データを取得してvaluesへ代入
      gapi.client.sheets.spreadsheets.values.get({
        spreadsheetId: SPREADSHEET_ID,
        range: SPREADSHEET_TAB_NAME,
      }).then(function(response) {
        values = response.result.values;
      });
    })
  }, function(error) {
    console.log('error', error);
  });
}

// ボタンをクリック時に実行
$('#btn').click(() => {
  const input = $('#input').val();
  let html = '▼情報';

  for(let value of values){
    if(value[0] == input) {
      for(let i=1; i<value.length; i++){
        html += `<br>${columns[i]}：${value[i]}`;
      }
    }
  }
  $('#displayText').html(html);
});
```

次回はスプレッドシートIDとシート名を
オプションから設定できるようの機能追加していきます。

# 補足

本当はsetTimeoutではなくて、全て読み込み終わったら実行にしたかったのですが、
設定方法がわからなかったので、なくなくsetTimeoutを使用しています。

スプレッドシート情報も全データを取って、オートコンプリートを作成するかとか、
ボタンをクリックしたときに再度情報を取りにいくかとか迷ったのですが、
これが一番スマートかなと思い、ブラウザアクション的にアイコンをクリックしたときに
2回情報を取りに行くようにしてみました。

あと今回詰まったポイントが`background`で`chrome.browserAction.onClicked.addListener`を
使いたかったのですが、`browser_actionのdefault_popup` とは併用できないということで諦めました。