ブックマークレット

作成日 : 2013-09-23
最終更新日 :

ブックマークレットとは

ブックマークレットとは、 ウェブブラウザのブックマークで起動し、ブラウザの情報を参照したり更新したりするプログラムをいう。 通常は JavaScript で実装される。

通常のブックマークでは、プロパティを見ると URL が次のように記載されている :
https://jsprimer.net/
そしてこのブックマークを選ぶと、その URL にページが遷移する。
これを javascript: から始まる JavaScript のコードで書き換える。さて、このブックマークを選ぶとどうなるかというと、 あら不思議、 ページは遷移せず(するのもあるが)、ページの情報を取得できたり、ページを書き換えたりできる。 以下説明するブックマークレットで、その挙動を説明する。

hello, world の表示

javascript:alert("hello, world");

現在のページに関係なく、単にポップアップで hello, world とポップアップする。

テキスト入力 (id 指定の場合)

javascript:(function (){let s=document.getElementById('IDENTIFIER');s.value='VALUE';})();

現在のページで、入力欄が <input type="text" id="IDENTIFIER"> のように記述されているテキスト入力欄があれば、 このブックマークレットを実行すると入力欄に VALUE が入力される。

テキスト入力 (name 指定の場合)

javascript:(function (){let s=document.getElementsByName('NAME')[0];s.value='VALUE';}) ();

現在のページで、入力欄が <input type="text" name="NAME"> のように記述されているテキスト入力欄があれば、 このブックマークレットを実行するとname="NAME" が指定されている最初の入力欄に VALUE が入力される。

チェックボックストグル

チェックボックス1 チェックボックス2 チェックボックス3 チェックボックス4

オプションの選択

オプションとは、複数の選択肢から一つを選ぶダイアログの形式である。 通常のインターフェースではラジオボタンを用いる。下記のスクリプトでは、 名称が selection_1 となっている複数の入力から値が radiobutton_3 となるものをチェックする。 下記の表示は、名称 selection_j の値 radiobutton_k をとるものが、 オプション j-k を表している。 現在の状態が何であっても、ブックマークレットを起動するとオプション1‐3がチェックされることを確認されたい。

オプション1―1 オプション1―2 オプション1―3

オプション2―1 オプション2―2 オプション2―3

DOM 構造

これをブックマークレットに入れておけば、DOM 構造が見える。

link オブジェクト

リンクオブジェクトで、onclick 属性があるものを引っ張ってみた。

なお、リンクオブジェクトは let d = document.links を使うことで、配列 d が得られる。この document.links は、A 要素と AREA 要素に適用されるが、 LINK 要素には適用されない。リンク要素が LINK であるリンクオブジェクトの配列 l を得るには、 let l = getElementsByTagName("link")とする。下記に例がある:
https://developer.mozilla.org/ja/docs/Web/API/HTMLLinkElement/rel

select 要素

select 要素は複数の選択肢から一つを選ぶダイアログの形式である。 これについてはオプションと同じであるが、 インターフェースが「ポップアップメニュー」「ドロップダウンメニュー」「リストメニュー」 などの形をとる。ラジオボタンと異なるのは、選ぶ前では選択肢が一部しか見えていないということだ。 昔習ったインターフェースの知識では、選択肢がすべて見えるようにラジオボタンを使うのが原則である、 ということだった。

さて、selecte 要素のブックマークレットの例である。上から順番に i (i = 1 ... 4) 番目の分野で、 i 番目の項目が選ばれるしかけになっている。

好きな果物:
好きな音楽家:
好きな点心:
好きな言語:

内と外

自分のページをインターネット上で見ていて、誤りを見つけたとする。そのとき、エディターを起動して訂正するが、 その後イントラネット(というより localhost )で誤りが訂正されたことを確認したい。 そのときのためのブックマークレットである。

ボタンの自動クリック

ログイン画面などで、IDとパスワードを入力してログインボタンをクリックすると先に進むことがある。 これをブックマークレットで実現することができる。

上記は変数 document やメソッド getElementById が繰り返されていて、スペリングのあやまりによるバグを起こしやすい。 そこで同じ変数やメソッドを統一して扱えるように短縮したのが次の記述である。この方法は、リンク集5に拠った。

注意:下記はサンプルのため送信できない。上記ブックマークレットを実行したり、下記[送信]ボタンをクリックしたりしたときの動作は、 単にこのページの上部に戻るだけである。

ID : PASSWORD :

ボタンクリックのイベントで submit 関数が起動されない場合は、button 要素の可能性がある。 そのときは次のようにする。ただし、ボタンに id 属性として "botton2" が定義されているとする。また、短縮形のみ掲げる。

注意:下記はサンプルのため送信できない。上記ブックマークレットを実行したり、下記[送信]ボタンをクリックしたりしたときの動作は、 単にアラートウィンドウを表示するだけである。

ID : PASSWORD :

ちなみに、input 要素には、ボタン(type='button')のほかに多くつかわれるものとして、テキスト(type='text')、パスワード(type='password')、 チェックボックス(type='checkbox')、ラジオボタン(type='radio') などがある。

ボタンの連続クリック

ボタンで画面ページを前後にめくるようなページでは使えるだろうか。かつてあった ASAHINet 掲示板 で試した結果である。

ここで、「HREFリンククリックによる別URLへの遷移」と「ボタンクリックによる同じURLにおけるPOSTメソッドの実行」に分けてみよう。 前者を A とし、後者を B とする。以下、A と B の操作について、適宜正規表現を使って表す。 まず、A 単独では次のようになる。

次に、B 単独では次のようになる。

ここまでくれば、AB という操作と BB という操作がどうなるか、考えてみよう。まず、同じ操作を行う BB から考える。 単純に次のように書くだけでうまくいかないだろうか。

試してみると BB ではなく、B だけである。なぜだろうか。全く同じ文を二度実行させているのもおかしいので、 文を関数として連続して実行するように書き直してみた。

しかし結果は BB ではなく、B だけである。おそらく、タイミングの問題なのだろうと考え、 タイミングを制御する関数を加えた。

しかし結果は変わらず、一度しかページは変わらない。setTimeout ではなく、次のようにsetInterval にしてみたが結果は変わらない。


面を繰る

前の問題は解けなかったが、その後も考えてみた。 もう少し簡単な問題を考えよう。次のような画面があるとする。



そして [次へ] のボタンをクリックすると次の画面が出るとする。


以上が次々とつながっているものとする。さて、 subsec001からsubsec010が出ている最初のページが徐々にページをめくっていき、 所望のsubsec[0-9][0-9][0-9]にたどり着く方法はあるだろうか。 仮に下記がフレームの下部にあるとする。上部はただのタイトルのページとする。 フレームのスクリプトは次のとおりとする。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" 
	  http://www.w3.org/TR/html4/frameset.dtd">
<html lang="ja">
<head>
  <meta charset="utf-8" />
  <title>Javascript Frame Control</title>
</head>
<frameset rows="*1,*5">
  <frame name="up"   src="title.html">
  <frame name="down" src="page0.html">
</frameset>
</html>

タイトルのページは次のようになるだろう。

<html>
<head>
  <title>Title</title>
  <meta charset="utf-8" />

  <script type="text/javascript">
    let id;
    let keyword = "subsec021";   // 探している文字列 
    function doNext() {
      let links = window.top.frames[1].document.links;

      for (let i = 0; i < links.length; i++) {
//      alert(links[i].text); // IE の場合は text のかわりに innerText かもしれない
        if (links[i].text == keyword) {
          window.clearTimeout(id);
          alert(keyword + "が見つかりました");
          return;
        }
      }
      let inputs = window.top.frames[1].document.getElementsByTagName('input');
      if (inputs.length < 1) {
        alert("何も見つかりませんでした");
        return ;
      }
      if (inputs[1].value != "次へ") {
        alert("何も見つかりませんでした。");
        window.clearTimeout(id);
        return;
      }
      inputs[1].click(); // [次へ] のクリック
      id = window.setTimeout("doNext()", 1000); // 1 秒後に次の画面を出す
    }
  </script>
</head>
<body>
<h1>Title</h1>
<p>
  <a href="javascript: doNext()">開始</a>
  <a href="javascript: window.clearTimeout(id)">停止</a>
</p>
</body>
</html>

以下を書こうとしたが、気力が尽きた。

ナビゲーションへのリンク

<link rel="reltype" href="url" /> などが head 要素に記述されている場合、 reltype に応じて指定されたリンク先 url に遷移する。下記ブックマークレットは、 reltype が "prev" の場合に指定されたリンク先 l[i].href に遷移する。

  javascript:(function (){const l=document.getElementsByTagName("link");
  for(let i = 0; i < l.length; i++)
    if (/^prev$/i.test(l[i].rel) === true)
      location.href = l[i].href
    })()

ここで、if 文の条件節は、「文字列 "prev" に l[i].rel が大文字小文字の区別なしで一致するならば」ということを意味している。 次の書き方も可能である。

  javascript:(function (){
    const l=Array.prototype.slice.call(document.getElementsByTagName("link"));
    p = l.find(e => /^prev$/i.test(e) === true)
    if (p !== null) location.href = p.href
    })()

const l=Array の行は、getElementsByTagName メソッドで得られる値の型が HTMLCollection であり、配列ではないため、 強制的に配列にすることを表している。このように配列になおせば配列型のメソッドである find などが使える。

下記ボタンをクリックすると、実際にこのページで指定されたページ(サーバサイド JavaScript)に遷移する。

リンク集

  1. ブックマークレット(jp.wikipedia.org)
  2. JavaScript::Bookmarklet(bookmarklet.daa.jp)
  3. chrome チェックボックス 全選択 全てチェック(peroon.hatenablog.com)
  4. select 要素を選択する小ネタ(d.hatena.ne.jp)
  5. 任意のサイトで自動ログインするブックマークレットを作る(d.hatena.ne.jp)

まりんきょ学問所JavaScript 手習い > ブックマークレット


MARUYAMA Satosi