Bookmarklet を 2 つ紹介（動画再生速度の変更、ツイート）

# Bookmarklet を 2 つ紹介（動画再生速度の変更、ツイート）

この記事に関係する範囲で自己紹介すると、

* 昨日「[AWS Training の動画を早送りしたい](https://qiita.com/irisTa56/items/72ca1aed18fa800088b3)」という記事を書いた
* スマホは iPhone を使っている
* できるだけブラウザを使いたい
  * アプリをインストールしたくない

という感じです。

## Bookmarklet で動画の再生速度を変更する

昨日書いた記事では、ブラウザの開発ツールで JavaScript を実行していましたが、bookmarklet にすれば良いのでは？と気付きました。

もとのコードは下記です。

```js
const videos = document.body.getElementsByTagName("video");
videos[0].playbackRate = 1.25;
```

Bookmarklet にするにあたって、global scope を汚染したくないので [IIFE](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) を使います。また、文字列にシングルクォーテーションを使います。ブックマークを HTML で export するときなど、URL をダブルクォーテーションで括る処理が行われる際に、予期しない動作が起こることを防ぐためです。

```js
(() => {
  const videos = document.body.getElementsByTagName('video');
  videos[0].playbackRate = 1.25;
})();
```

再生速度が `1.25` 倍にしかできないのでは融通がきかないので、ユーザが指定できるようにします。ユーザの入力は [`prompt`](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt) で受け付けます。ユーザがキャンセルを押したときは `null` が返ります。また、`videos` が空の可能性もあるので、そのチェックも追加しました。

```js
(() => {
  let rateInString = prompt('Playback Rate:', '1.25');
  if (rateInString === null || rateInString === '' || isNaN(rateInString)) return;
  const videos = document.body.getElementsByTagName('video');
  if (videos.length > 0) {
    videos[0].playbackRate = parseFloat(rateInString);
  }
})();
```

この生の JavaScript コードを bookmarklet に変換します。この変換をしてくれるウェブページがいくつかあって、オススメは [Bookmarklets construction set - Create bookmarklets online](http://js.do/blog/bookmarklets/) です。

無事に、AWS Training の動画の再生速度を変更できました（自分は Firefox で確認しました）。動画に `<video>` 要素を使っているのであれば、他のページでも同じように使えるはずです。

## Bookmarklet でウェブページを参照した tweet する

私が bookmarklet を知ったきっかけでもあるのですが、[この記事](https://qiita.com/munieru_jp/items/24a4840c452c61c2dde9)が大いに参考になります。ただし、一つ注意点があって、[iOS では `window.open` が期待通りに動きません](https://qiita.com/utautattaro/items/1d333d24162891f10372)。という訳で、下記のようなコードにします。

```js
(() => {
  const url = `https://twitter.com/intent/tweet?text=${encodeURIComponent(document.title)}%20${encodeURIComponent(location.href)}`;
  if (open(url, '_blank')) {}
  else { location.href = url; }
})();
```

たぶん、スマホではアプリじゃないと Twitter の詳細設定とかはできないと思います。でも、そういうのはパソコンでできれば OK という方は、ブラウザ完結にしてしまうのもシンプルで良いと思います！

## おわりに

プラットフォームを OS と考えるか、ブラウザと考えるか によって bookmarklet を便利に感じるかどうかも左右されるのではないかと思います。私は、少なくとも Web に関してはブラウザがプラットフォームであって欲しい（たとえモバイルであってもそうあって欲しい）と思っているので、今後も bookmarklet をつくっていきたいです！

## 追記 2019/07/06

iOS において、下記の問題が生じることに気付きました。

* Tweet の画面が開き、text と url もちゃんと入力されているが、新たな文字の入力ができない。

Bookmarklet を使わずに iOS の Safari で tweet する場合、`https://mobile.twitter.com/compose/tweet` が開きます。上に書いた bookmarklet では、iOS でも `https://twitter.com/intent/tweet` が開くようになっています。これが問題かな？と考え、下記のコードに変更したところ、問題が解消しました。

```js
(() => {
  const text = encodeURIComponent(document.title);
  const url = encodeURIComponent(location.href);
  const isMobile = /iP(hone|(o|a)d)/.test(navigator.userAgent);
  const URL = isMobile ? 'https://mobile.twitter.com/compose/tweet' : 'https://twitter.com/intent/tweet';
  const fullURL = `${URL}?text=${text}&url=${url}`;
  if (open(fullURL, '_blank')) {}
  else { location.href = fullURL; }
})();
```

Bookmarklet の情報は mobile を想定していない場合が多いのかもしれないので、しっかり検証しなければならないと感じました。