Amazon商品ページでKindle配信先を自動的に選択する Chrome（またはEdge）の拡張機能を作った（その１）

Kindle本を購入する際の配信先のデフォルトが設定できない。そこで、Amazonの商品ページにて、Kindleの配信先を自動設定するものをブラウザの拡張機能として作成した。
ただし、この機能は検索結果の「1-Click で今すぐ買う」で買うときの配信先は設定できない。あくまでも個々の商品ページにある配信先を設定するだけのものだ。

作成した版はふたつある。シンプルな実装版と、複雑な実装だが動きは速い版。
シンプル版はコメントと空行を除けばコードは10行程度。実装と動作がわかりやすい。
ただ、ページロード後に動作するので、配信先の設定が若干遅い。
速い版はページロード中に処理するため、瞬時に設定される。
今回はシンプル版を紹介し、速い版はその２で紹介する。
[Amazon商品ページでKindle配信先を自動的に選択する Chrome（またはEdge）の拡張機能を作った（その２）](https://qiita.com/happykorroke/items/df385a667dfedabc97e5)

```json:manifest.json
{
  "name": "Kindle DeliverTo Selector",
  "description": "Autoselect deliverTo Kindle device.",
  "version": "1.0",
  "manifest_version": 3,
  "content_scripts": [
    {
      "matches": ["https://www.amazon.co.jp/dp/*",
                  "https://www.amazon.co.jp/*/dp/*",
                  "https://www.amazon.co.jp/gp/product/*",
                  "https://www.amazon.co.jp/exec/obidos/ASIN/*",
                  "https://www.amazon.co.jp/o/ASIN/*"],
      "js": ["content_script.js"]
    }
  ]
}
```

```javascript:content_script.js
'use strict';

(function() {

	//デバイスID
	const deviceId = 'AL13906LU4VTW';
	//これを自分のデバイスIDに書き換えること
	//デバイスIDはHTMLソースにてSELECTエレメント(id="deliverTo")を調査すれば分かる

	//配信先のエレメントを取得
	//このidを持つSELECTエレメントは通常、注文用とサンプル送信用とふたつある
	const elems = document.querySelectorAll('select#deliverTo');

	//各SELECTエレメントを処理
	for(const elem of elems) {
		// 値がdeviceIdと一致するOPTIONエレメントを検索
		if(elem.querySelector('option[value="' + deviceId + '"]')) {
			//存在する場合、SELECTエレメントに値を設定
			elem.value = deviceId;
			//changeイベントを発火。bubblesをtrueにして先祖エレメントにイベントを伝播させる
			elem.dispatchEvent(new Event('change', { bubbles: true }));
		}
	}
})();
```

<b>インストール方法</b>

<b>1. ファイルの保存</b>
上のふたつのコードをコピーして自分のローカル端末に保存する。
ファイル名は manifest.json, content_script.js にして、ファイルのエンコードはUTF-8で保存する（BOM付き、なし、どちらも可）。エンコードの指定は、だいたいのどのエディタも「名前を付けて保存」で文字コードを選べる。
ふたつのファイルは同じフォルダに格納する。フォルダ名は任意でいい。

<b>2. スクリプトに自分のデバイスIDを書き込む</b>
(1) Amazon にログインした状態で、Kindle本の商品ページを開く。
(2) Ctrl + U を押して、ページのHTMLソースを表示する。
(3) "deliverTo" で検索して（二重引用符も含めて検索） selectエレメントを探す。（ちなみに親のdivエレメントもidは"deliverTo"である）
(4) 配信先として選びたいデバイスをselectエレメントの配下から探す。
(5) (4) で見つけた option エレメントの value の値（AL13906LU4VTWのような値）をコピーする。
(6) 先ほど保存した content_script.js を開き、コピーしたデバイスIDを貼り付ける。
![deliverTo説明付き.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90442/f1addb94-4190-593b-119a-ff9fc68ab56e.png)

<b>3. ブラウザにインストールする</b>
下記の通りインストールする。

Chromeなら
(1) 画面右上の隅のジグソーパズルのピースをクリックして「拡張機能の管理」を開く。
 　 あるいは、右上の隅の ［  ⁝  ］を押し「その他のツール」→「拡張機能」を開く。
(2) 拡張機能の設定画面が開かれたら、右上の「デベロッパーモード」をオンにする。
(3)「パッケージ化されていない拡張機能を読み込む」をクリックする。
(4) スクリプトが格納されたフォルダーを選択する。

Microsoft Edgeなら
(1) 画面右上の隅の［･･･］を押し「拡張機能」を開く。
(2) 拡張機能の設定画面が開かれたら、左下の「開発者モード」をオンにする。
(3)「展開して読み込み」をクリックする。
(4) スクリプトが格納されたフォルダーを選択する。

Firefoxなら
以下の手順で一時的にインストールできる。
パッケージ化していないので永続的なインストールは不可。
(1) 画面右上の隅の［≡］を押し「アドオンとテーマ」を開く。
(2) アドオンマネージャ―が開かれたら、歯車ボタンを押し「アドオンをデバッグ」をクリックする。
(3)「一時的なアドオンを読み込む...」をクリックする。
(4) ファイルダイアログで manifest.json を選択する。
※「Unsupported manifest version: 3」のエラーが出るなら、上の manifest.json の "manifest_version" を 2 に書き換える。

<b>解説</b>
プログラム理解のため、少し説明する。

<b>配信先関連エレメントについて</b>
商品ページの配信先の選択には主に以下の３つのエレメントが関わっている。

<b>SELECTエレメント</b>（id="deliverTo"）
選択された配信先の値を保持する。
このSELECTエレメントは非表示になっており、ユーザーからは見えない。
配下の各OPTIONエレメントの値がデバイスIDである。

<b>ULエレメント</b>
配信先をクリックした際、このエレメントがドロップダウンリストとして表示される。
このエレメントはSELECTエレメントのclickイベントによってbodyの一番下に、動的に追加される。

<b>SPANエレメント</b>
このSAPNエレメントはドロップダウンが閉じているとき表示される。
子のエレメントは持たず、配下にはデバイス名が書かれたテキストのみを持つ。
この内部テキストは、SELECTエレメントのchangeイベントによって更新される。
スクリプトでSELECTエレメントの値を設定しただけでは、表示されているデバイス名は変わらない。
dispatchEventのオプション引数bubblesをtrueにして、イベントが祖先エレメントに伝播するようにするよう change イベントを発行すれば、このSPANの内部テキストが更新される。
今回のシンプル版はそのようにしてるが、動きの速い方の版では イベント処理に任せず、このSPANのテキストは自前で書き換えている。