Google Chrome 拡張機能の開発 - 9 - ページの閲覧を便利にする（アンカー追加、折りたたみ）

#やりたいこと
例えば、とある記事を読んでいて、そのページ内の別の場所を読みたい時に一時的に目印を付けておきたい場合や、前後を見やすくするために、折りたたみをしたい場合があります。
きっとちゃんと探せばそういったものはありそうですが、見つからなかったので、次のような事をする拡張機能を作る事にします。

- コンテキストメニューから「ここにアンカーを追加」で、その場所にアンカーを埋め込み、ページの上部にそのアンカーへのアンカーも追加する
- コンテキストメニューから「ここを折りたたみ」で、その場所にdetails要素を追加する

#コード
一式はこちら： https://github.com/rrryutaro/RChromeExtension

```json:manifest.json
{
   "background": {
      "page": "background.html"
   },
   "content_scripts": [ {
      "matches": [ "<all_urls>" ],
      "js": [ "jquery-3.1.1.min.js", "contentscripts.js" ],
      "run_at": "document_end",
      "all_frames": true
   } ]
}
```

```javascript:background.js
chrome.contextMenus.create({title: "ここにアンカーを追加", contexts: ["all"], onclick: info=>{
  chrome.tabs.getSelected(null, tab=>{
    chrome.tabs.sendRequest(tab.id, {command: "AddAnchor"});
  });
}});

chrome.contextMenus.create({title: "ここを折りたたみ", contexts: ["all"], onclick: info=>{
  chrome.tabs.getSelected(null, tab=>{
    chrome.tabs.sendRequest(tab.id, {command: "AddDetails"});
  });
}});
```

```javascript:contentscripts.js
//現在マウスホバー中の要素
let hoverTarget;
//コンテキストメニューを開いた際にマウスホバーしていた要素
let selectionTarget;
//アンカー追加用のカウント
let addAnchorCount = 0;

//マウスホバー中の要素を保持する
$("*").hover(e=>{
  hoverTarget = e.target;
},e=>{});

//コンテキストメニューを開いた際にマウスホバー中の要素を保持する
$("*").bind("contextmenu",()=>{
  if (selectionTarget !== hoverTarget){
    selectionTarget = hoverTarget;
  }
});

chrome.extension.onRequest.addListener((request, sender, sendResponse)=>{
  //アンカーを追加する
  if (request.command === "AddAnchor" & selectionTarget != null){
    var target = $(selectionTarget)[0];

    var linkName = "AddAnchor" + ++addAnchorCount;
    var displayName = target.outerText.substr(0, 10);

    target.innerHTML = "<a name='" + linkName + "'></a>" + target.innerHTML;

    var newAnchor = document.createElement("a");
    newAnchor.innerHTML = "<a href=#" + linkName + ">" + displayName + "</a>";
    $(document.body).before(newAnchor)
  }
  //ディスクロージャー・ウィジェットを追加する
  if (request.command === "AddDetails" & selectionTarget != null){
    var target = $(selectionTarget)[0];
    var summary = target.outerText.substr(0, 20);
    target.innerHTML = "<details><summary>" + summary + "</summary><div>" + target.innerHTML + "</div></details>";
  }
});
```

#使用例
次の部分で「ここにアンカーを追加」をクリックする。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/156225/da952d8e-42e6-bf52-dec9-69c7c1a4f576.png)|
|:--|

ページ上部にリンクが追加されて、クリックすれば先ほどの場所へ飛ぶ。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/156225/4b0b9f19-45f8-ebd6-9cfb-8cc524c3ac58.png)|
|:--|

次のように文章部分で「ここを折りたたみ」をクリックする。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/156225/ba7699e0-d51e-3323-4364-a65ee3cbad3c.png)|
|:--|

折りたたまれる。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/156225/0cb8eba0-86ad-bce0-7a8e-971fd6bba3b8.png)|
|:--|

#課題
とりあえず、最低限の動作はできるようになったので、ここからは実際に使いやすいように修正をしていくことになります。
特にリンクの追加はもっと良い方法を考えたいです。
JavaScriptはあまり詳しくないので、いまはこの程度の方法です。

また、折り畳みについてはもう少し知的な対応を行なって、見出し部分を選んだ場合、次の見出しまでを折りたためるようにすれば、結構使えるようになるのではないかと思います。

その他、今はリンクの名前も折りたたみ時の表示も字も、固定値で切り取っているため、この辺を利口にするなり、オプションで設定できるようにするなどや、ショートカットの指定なども。

#公開先
[R Chrome Extension - Chrome ウェブストア](https://chrome.google.com/webstore/detail/r-chrome-extension/nmabekdmfpblgbgplficnahfkekbggil?hl=ja)

以上

|前回|一覧|次回|
|:--|:--:|--:|
|[(2017年12月)1年ぶりなのでもう一度はじめの一歩](https://qiita.com/rrryutaro/items/e6b98a0354d67c481a93#AddAnchor1)|[シリーズ一覧](http://qiita.com/rrryutaro/items/015b67568ddd947ec2b5)|(まだ)|