Bookmarkletを作ろう(準備編）

業務効率化のためにブックマークレット~~で遊ぶ~~を学ぶ

# このページは
Bookmarkletの作り方とテストの仕方をメモします。
ブックマークレット自体の説明は省きます。googleで検索するとたくさん出てくるので探してください。

# 今回使うもの
javascript
[google closure compiler](https://closure-compiler.appspot.com/home) 

# Bookmarkletの作り方
## 基本編
BookmarkletはJavascriptで記述されたプログラムなので、コードを書きましょう。ありがちなhello worldからいきます。知っている人は読む必要ないですね。

```javascript
alert('はろーわーるど');
```

このコードが動くとalert boxが表示されます。どうやって動かすのか、それが一番の関心事です。

##動かし方　その１
ブラウザのアドレスバーにコードをコピーして動かします。先頭に**javascript:** を足してjavascriptのコード全体を貼り付ける。

```javascript
javascript:alert('はろーわーるど'); 
```

やってみると分かりますが、上のコード全体をコピーして貼り付けても、アドレスバーでは**javascript:**が消されてしまいます。

大事なことは、
アドレスバーにjavascript:を書いてから、javascriptのコードだけを貼り付ける。これで動かすことができるはずです。

最近気が付いたこと。先頭に**javascript:**と書くから消えるのであって

```javascript
//javascript:alert('はろーわーるど'); 
```

とコメントアウト版で書いてアドレスバーに貼ってから、//を消すほうが手数が少ないなと思ってます。


##動かし方　その２
ブラウザのブックマークに**javascriptのコード**を登録してブックマークとして呼び出します。

1. ブックマークを呼び出す
2. ブックマークとして登録したコードがアドレスバーに移される
3. 今開いているブラウザでコードが実行される

という仕組みです。
ブックマークをクリックしやすくないと意味がないのでブックマークバーに登録することが多いです。開発中、何度もコードを書き換えるたびにブックマークを編集するのが面倒なので、アドレスバーで何度か動かしてからブックマークに登録します。

ここまでは基礎の基礎です。

#ちょっと複雑版
練習以外でHello worldを作ることは無いと思うので、ちゃんとしたものを作るとjavascriptのプログラムもそれなりに長くなります。長いプログラムをbookmarkletにするとき、`Google Closure Compiler` を使うと便利です。

**サンプルのjavascript**
表示しているページのタイトル、URL、Canonicalをalertするjavascript

```javascript
javascript:(
    function(){
      title = document.title;
      href = document.location.href;
      canonical = get_canonical();
      console.log('ページタイトル=%s \n href=%s \n カノニカルURL=%s', title, href, canonical);
      alert('ページタイトル：'+title +"\n現在のURL："+href + "\nカノニカルURL：" + canonical);
  
      function get_canonical(){
        links = document.getElementsByTagName("link");
        for ( i in links) {
            if (links[i].rel) {
                if (links[i].rel.toLowerCase() == "canonical") {
                    return links[i].href;
                }
            }
        }
        return "";
      }
    }
  )();
```

##クロージャーコンパイラを使う
[google closure compiler](https://closure-compiler.appspot.com/home) を使うと、Javascriptのコードを事前にコンパイルしてくれます。コンパイル時に構文エラーを教えてくれるので助かります。しかも改行や空白もキレイにしてくれて1行にまとめてくれるので、長いbookmarkletを作るときにはとって便利です。

Closure Compilerの使い方はこちらにあります。
https://developers.google.com/closure/compiler/docs/gettingstarted_ui

###コンパイルしてみる
Closure compilerを開き、先ほどのコードを左の枠に貼り付けて、Compileボタンを押すだけ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/168315/0df9d179-b51b-99ac-3a46-3ca5d192de9e.png)

コンパイルが成功すると、右側にコンパイル済みのコードが出てきます。（この例では、たいして短くなってないですけど、短くなります）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/168315/81aef269-675a-2996-03ff-47752e7eceaa.png)

コンパイルしたコード（画面の右側に出力されるもの）をアドレスバーに突っ込めば、そのコードが表示しているHTML内で動きます。基礎編のその1の動かし方です。

コンパイルしたコードが極めて長くなってしまう場合には、こちらの記事を参照すると幸せになれるかもしれません。
https://qiita.com/kanaxx/items/b3aa057a11002788ec46

コードの先頭部分に、コンパイラー用のオプションを入れると良いことあるかも。

```javascript
// ==ClosureCompiler==
// @output_file_name default.js
// @compilation_level SIMPLE_OPTIMIZATIONS
// @language_out ECMASCRIPT_2017
// ==/ClosureCompiler==
javascript:(
```


##Chrome Dev Toolのコンソールから動かす
2020年に知った驚愕の事実。
実際にブックマークレットを開発・テストしているときは、コンパイラーを通してアドレスバーに貼り付けるなど面倒な作業をせず、この方法でやることにしました。

[Chrome Dev Toolでブックマークレットを実行する](https://qiita.com/kanaxx/items/0fe8e7e2deea482960b0) 　

#コードをブラウザに設定する
作ったコードをブラウザのブックマークに設定をしたら完成です。ブックマークにjavascriptのコードを埋め込む方法も紹介します。

##ダミーのブックマークを作って編集する方法
一番お手軽なやり方です。

1. まず、ブラウザでどこかのページを開きます。googleのトップでも楽天のトップページでもqiitaでもどこでもよいです。
2. 開いたページをブックマーク（お気に入り）に登録します。ChromeならCTRL+D
3. 登録したブックマークを編集ボタンで開き、URLの部分を全て削除します。先頭を```javascript: ```に書き換え、その後ろにコンパイルしたコードを貼り付けて登録します。ブックマーク名は分かりやすいものに書き換えてOKです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/168315/a39e1060-a0c6-8706-da08-a1b6f4b32220.png)

上はchromeの場合



##HTMLページのAタグで渡す
Aタグのhrefにjavascript:で始まるスクリプトを書き、ページをブラウザで開くとリンク表示されます。リンクをブックマークバーまでドラッグ＆ドロップすることで簡単にブラウザに設定できます。利用者が複数いるような環境では、この方法が便利です。コンパイルしたjavascriptにダブルクオートが含まれているとHTMLのリンクが途中で切れてしまうので、`&quot;`に置換してください。

```html
<a href="javascript:(function(){title=document.title;href=document.location.href;a:{links=document.getElementsByTagName(&quot;link&quot;);for(i in links)if(links[i].rel&&&quot;canonical&quot;==links[i].rel.toLowerCase()){canonical=links[i].href;break a}canonical=&quot;&quot;}a=console.log(&quot;title=%s \n href=%s \n cano=%s&quot;,title,href,canonical);console.log(a);alert(title+&quot;\n&quot;+href+&quot;\n&quot;+canonical)})();">ブックマークレットのリンク</a>
```


##HTTPでアクセスできるところにおいて取り込む
jsファイルをサーバーにアップして取り込む方法もあります。HTTP/Sでアクセスできるサーバーが必要になりますが、ブラウザから実行するたびにサーバーにアクセスし最新のjsファイルを取得する形になるので、ファイルを置きかえるだけでバージョンアップができます。
サーバーに置く場合には、ClosureCompilerを通したファイルにしなくても大丈夫です。

**■サーバーにアップする**　
上のサンプルをどこかにアップします。今回はcloudinaryにアップしました。
https://res.cloudinary.com/kanaxx/raw/upload/v1532235146/bookmarklet/bookmarklet_sample.js

**■ブラウザに設定する**
ブラウザには以下の形で設定します。

javascript:(function(d,j,s){s=d.createElement('script');s.src=j;d.body.appendChild(s);})(document,'**https\://res.cloudinary.com/kanaxx/raw/upload/v1532234732/bookmarklet/bookmarklet_sample.js**')

[ブックマークバーに登録した後にメンテナンスしやすいブックマークレットを作るコツ](https://qiita.com/kanaxx/items/d5a0591336cc2cc55783) の記事を書きました。ブラウザに登録する時の工夫を書きましたので、参考にどうぞ。

##HTTPでアクセスできるところに置いてimportする
※2020年8月追記

この形がクールですね。 [^2]: 
[^2]: https://qrunch.net/@okayu/entries/oCXiY7zM7yBhjhV0

Bookmarkletのコード本体は、即時関数ではなくて普通の関数にし、どこかにホストしておいて
ブラウザ側で、ファイルを`import`し、読み込み終わったら`default`関数を実行する形です。

**■サーバーにアップする**　

```javascript:canonical_exported.js
export default () => {  
    let title = document.title;
    let href = document.location.href;
    let canonical = get_canonical();
    console.log('ページタイトル=%s \n href=%s \n カノニカルURL=%s', title, href, canonical);
    alert('ページタイトル：'+title +"\n現在のURL："+href + "\nカノニカルURL：" + canonical);
    
    function get_canonical(){
      let links = document.getElementsByTagName("link");
      for ( let i in links) {
        if (links[i].rel) {
          if (links[i].rel.toLowerCase() == "canonical") {
            return links[i].href;
          }
        }
      }
      return "";
    }
}
```

**■ブラウザに設定する**

```javascript
avascript: void (import('https://kanaxx.github.io/bookmarklet/canonical_exported.js').then(m => m.default())); 
```




https://github.com/kanaxx/kanaxx.github.io/blob/master/bookmarklet/canonical_exported.js

#応用版
ブックマークレットのプログラムとテストを実行する場合、以下の手順を繰り返すことになります。

1. エディタでコードを書く
2. Closuer Compilerにコピー、コンパイル
3. 右側のコードをコピーする
4. アドレスバーにフォーカス当てる
5. javascript:とタイピング
6. コンパイル済みのコードを貼り付け
7. 実行

まぁ、面倒ですね。1日5回が限界。



##default.jsを使う
このマニュアルの中に、気になる一文があります。
>For your convenience, the Closure Compiler service hosts the output file default.js on its servers for one hour. You can access the URL of the output file by copying the location of the link that's provided above the output pane, where it says The code may also be accessed at {filename}.

簡単に訳すと、
*あなたの開発を便利にするために、Closure Compilerサービスは出力したファイルを1時間default.jsという名前でHostします。出力画面にあるURLをコピーするだけで出力ファイルにアクセスできます。*

というわけで、Closure Compilerでコンパイルしたファイルは、googleのサーバーにアップされていてHttpでアクセスできるようになってます。下の画面のdefault.jsのリンクです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/168315/c7f26173-ea11-15f2-dae4-b91cff6ddcfb.png)



default.jsのリンク先はこのような感じです。（1時間経過しているのでクリックしても何もないはずです）
>https://closure-compiler.appspot.com/code/jsc328c01f4982838d888b9be850c219f8/default.js

**jsc328c01f4982838d888b9be850c219f8**の部分が人によって変わります。最初に生成してから1時間だけ使えます。1時間経つと無効になります。コンパイル後のコードが長くなったときにはブラウザで選択するのも面倒なので、default.jsを開き、CTRL+Aで全体コピーがよいです。

それでもまだ面倒です。では、最終形にいきます

##default.jsを動的に読み込むBookmarkletを作る
default.jsが外部公開されて、httpで持ってこれるのであれば、bookmarkletでdefault.jsを参照してしまいましょう。bookmarkletで外部のスクリプトファイルを参照する方法を使ってgoogleのサーバー上にあるdefault.jsを読み込むbookmarkletを作成します。

```javascript
javascript:(function(d,j,s){s=d.createElement('script');s.src=j;d.body.appendChild(s);})(document,'//closure-compiler.appspot.com/code/jsc328c01f4982838d888b9be850c219f8/default.js')
```
コードの書き方はいろいろとあると思いますが、自分が使っているのはこれです。（何かを参考にしたのですが忘れました、すいません。）
最後の引数がdefault.jsのURLになっているので、default.jsのURLが無効になったら自分のブラウザのBookmarkletのURLを編集します。

1. コードを書く
2. Closuer Compilerにコピー、コンパイル
3. default.jsを呼び出すbookmarkletで実行する

とてもシンプル


これはあくまでテスト段階の動かし方です。1時間で消えますから、ずっとは使えないです。うまく動くことが確認できたら、コンパイル済みのコードを利用者のブラウザのブックマークに登録するか、default.jsと同じ内容を1時間で消えないところに置いておく必要があります。

##default.jsを使うときの注意点
Closure Compilerのマニュアルに以下の注意文があります。
>Note: To prevent abuse, the Closure Compiler limits the number of consecutive compiles that you can run. If you see the message Too many compiles performed recently. Try again later, it means you've temporarily exceeded the limit.

コンパイルを何度もやるとエラーメッセージが出ることがあるので、その時はちょっと待ちましょう。とのことです。

#まとめ
今日はBookmarkletの動かし方と、開発中の動かし方を書きました。
次回は、jQueryを使ってサイト内をデータを取り出して遊ぶ方法を書く予定です。


#こちらもどうぞ
[Bookmarkletを作ろう（ウェブページのハック手順編）](https://qiita.com/kanaxx/items/ead7d7b12619a578b7fe)