入門編! ブックマークレットを作ってみる - JavaScript プログラミング

PROGRAM


入門編! ブックマークレットを作ってみる

ブックマークレットの良さにようやく気が付きました。

2013.07.20 に開催された iPhone Blog Cafe に参加させて頂いて、ブックマークレットというものを初めて知りました。

いえ、存在そのものはどこかで耳にしていて仕組みもさらっと調べて見てはいたのですけど、自分の理解は「便利なものみたいだな」とか「ちょっと準備が大変そう」とか止まりで、その本当の素晴らしさを理解できていませんでした。

 

そんなブックマークレットでしたけど、講師の あかめさんこれは絶対便利だからと念入りに説明してくれたおかげで、ようやくその真の良さに気が付くことができました。

いや、そう言ってくれただけでは、まだ自分は理解できていなかったかもしれません。

勉強会では実習の場を 2 度も設けてくれて準備の面倒意識が払拭されたこと、目の前で綺麗なシェアリンクをさくっと作って見せてくれたこと、ブログはパーツを作って組み上げると教えてくれたこと。

これのどれかが欠けていたら、きっと今も自分はブックマークレットを知ったつもりで過ごしていたことでしょう。

ブックマークレットって?

ブックマークレットというのは、小さな機能を持たせた JavaScript をブックマークに登録しておいて、必要な時に簡単にそれを実行できるようにしておく手法です。

JavaScript で作成するので、たとえば DOM を辿ってページの中からタイトルなどの情報を取得したり、サイト内の情報を使って別のページにジャンプするなどはお手のものです。

任意のテキストに色を付けたり、画像の数を数えたり、頑張ればたぶんページの更新日とかも取得できそうな気がします。

 

好きな JavaScript を作成したら、それをブックマークに登録するだけ。

あとは好きなページでお気に入りから選ぶだけで、そのページ上でブックマークレットを簡単に実行することができます。

使いたくなって、作りたくなってきました。

iPhone Blog Cafe で詳しく教わったブックマークレットは次の二つでした。

Tabelog2html 食べログのページから、そこに掲載されている情報を使ってブログ掲載用の HTML を生成してくれます。
ShareHtml 表示中のページを、サムネイル付きで紹介できる HTML を生成してくれます。

どちらもさくさくっと、きれいなフォーマットで情報を揃えてくれるからすごいです。

用意する手間はちょっとで最初だけ、あとはこれを「いい!」と思ったページで実行して、生成された HTML をブログに貼るだけで紹介リンクができてしまう、なんて便利なんでしょう。

これらのブックマークレットが多くの人に好かれているわけです。

 

そんなブックマークレットを知って数日、自分のサイトでも他の人のページを紹介したい場面が登場しました。

さっそく ShareHtml を設定して、試しに あかめさん のページリンクを作ってみると、ボタン一発でいとも簡単に素敵なブログリンクが出来上がりました。

なにこれ、とってもいい!

スタイルシートとかで手入れをしてあげれば、それぞれのサイトに馴染む紹介リンクをどんどん作って行けますね。

 

リンクをシェアするブックマークレットを作ってみる

さて、実際に動くものを見て感動すると自分でも作ってみたくなるのはプログラマーの習性なのか、自分でも ShareHtml の簡易版みたいなブックマークレットを作ってみたくなってきました。

 

機能としては、タイトルと詳細説明を引っ張ってくる感じにしてみましょうか。

サムネイルも引っ張ってきたいところですけど、時間の都合でそれはまた追って追加しようと思います。

何もしないブックマークレットを作ってみる。

とりあえず今回は Mac の Safari で動作するブックマークレットを作ってみようと思います。

 

ブックマークからブックマークレット呼び出したときに JavaScript を実行したいので、肝心な内容はまず "javascript:" から始めます。

そしてブックマークレットが不必要に外と干渉しないように、外側にひとつ匿名関数 "function() { }" というものを作成して、それを実行してあげるのが良さそうです。

作成した匿名関数は、その全体を ( ) で括り、後ろに続けて () を記載することで実行できます。

そして、JavaScript のルール上、文末には ";" を記入します。

 

そんな辺りを意識して何もしないブックマークレットを定義すると、次のようになりました。

javascript:

(

function()

{

/* ここでブックマークレットの機能を実装します。*/

 

}

)

();

上記では見やすいようにインデントしてあります。

このあたりは慣れないと判りにくいところですけど、重要なところでもないので、こういうものだと思って覚えてしまえば大丈夫でしょう。

ブックマークレットの登録方法と留意点

ブックマークレットの登録は、Safari 6.0.5 の場合は、予めテキトウなページをブックマークに登録して、アドレスのところをブックマークレットのソースコードで上書きします。

これで登録完了です。

あとは、ブックマークから登録したこのブックマークレットを選ぶことで、そこに記載されているコードを実行できます。

 

このとき、本来であれば、実際にコードをブックマークに登録するときは、全体を URI エンコードする必要があります。

ただ、とりあえず今回紹介するブックマークレットなら、そのまま Mac の Safari 6.0.5 にブックマークのアドレスにペーストすれば自動調整されるようでしたので、そういった難しいことは無視して話を進めて行きます。

本来のエンコードが必要な場面については こちら をご覧ください。

コメントについて

ちなみに "/*  */" で括られている部分は、実行時には無視されるコメントです。

JavaScript では他にも "//" を使ってコメントを書くこともできるのですけど、ブックマークレットの JavaScript のように 1 行で全てを記載したいときには向かないと思います。

何かメッセージを表示してみる。

何もしないブックマークレットでは面白味がないので、とりあえず何かメッセージを表示するだけのブックマークレットにしてみましょう。

JavaScript でアラートメッセージを表示するには "alert" 関数に表示したい文字列を引数として渡します。

 

JavaScript では、文字列は "" または '' で括って指定するのと、引数は関数の後ろに ( ) を使って指定するので、たとえば "ブックマークレット!" というメッセージを表示したければ、実装部分は次のようになります。

末尾はいつも、JavaScript の構文ルールに倣って ";" です。

alert('ブックマークレット!');

つまりこれを、先ほどの枠組みに入れ込んであげると、次の通りになります。

javascript:

(

function()

{

alert('ブックマークレット!');

}

)

();

これをブックマークに登録して実行すると、画面上に次のようにメッセージボックスが表示されました。

何の役にも立たないブックマークレットですけど、とりあえず期待通りに動いてくれましたね。

これは楽しくなってきました。

サイトのタイトルを取得してみる。

でも固定メッセージを表示するだけでは、ブックマークレットの意味がありませんね。

そこでリンクの共有で必要不可欠な、そのサイトのタイトルを取得してそれを表示するようにしてみようと思います。

 

JavaScript ならサイトのタイトルを取得するのは簡単です。

ページ全体の情報を持つ "document" の "title" の値を取得することで、そのページのタイトルを取得することができます。

 

アラートメッセージとして表示させるなら "alert" 関数の引数に document.title を渡すだけで実現できます。

javascript:

(

function()

{

/* アラートメッセージでサイトのタイトルを表示します。*/

alert(document.title);

}

)

();

そしてこれを好きなサイトで実行すれば、簡単にサイトのタイトルを表示することができました。

ちょっとですけど、だんだんとブックマークレットらしくなってきました。

取得したタイトルをタグで修飾する。

今回は、最終的にはブログに貼るHTMLを作成するのが目的なので、取得したサイトのタイトルに HTML でマークアップしてみます。

とりあえず、次のようにしてみましょうか。

<div class="ez-sharelink">

<div class="ez-shared-title">

サイトのタイトル

</div>

</div>

このような構造にしてみようと思います。

シンプルな構造ですけど、これを CSS を使って見た目を整えればこのままでも十分活用できることでしょう。

また、目的の HTML を作成する方法はいくつかありそうですけど、少し難しいながらも理解できれば解りやすく応用が利きやすい DOM (Document Object Model) を使った方法でやってみます。

 

まず、流れを整理すると

どんな風に作って行くか、まずは混乱しにくいように整理してみます。

  1. "外側の <div> ノード" を作成する。(class="ez-sharelink")
  2. "内側の <div> ノード" を作成する。(class="ez-shared-title")
    1. "外側の <div> ノード" に "内側の <div> ノード" を追加する。
  3. "サイトタイトル" を取得する。
    1. "サイトタイトル" を使って "テキストノード" を作成する。
    2. "内側の <div> ノード" に "テキストノード" を追加する。
  4. "外側の <div> ノード" から HTML を取得する。

ステップは少し多いですけど似たようなことを繰り返しやってるだけで、要は生成するタグを順に作成して、そのひとつ外側に登録している感じです。

 

ちなみにノードというのは、タグとか、テキストとか、それぞれ単品みたいなものです。

タグの場合はさらに子ノードを持つことができます。内側のタグとか、タグで囲まれたテキストとかが子ノードですね。

 

1. 外側 <div> ノードの作成

HTML タグのノードは "document.createElement" 関数を使って作成します。

/* 外側 div ノードを作成します。*/

var frameNode = document.createElement('div');

ちなみに "var" に続けて指定したものが変数名です。

ここでは "frameNode" という変数名に、作成した <div> ノードを入れているので、以降はこの "frameNode" という変数を使ってノードを編集して行けます。

 

そして、この内側の <div> ノードには、今回は "ez-sharelink" というクラスを設定したいので、次のように "className" プロパティを設定します。

/* 作成した div ノードに class="ez-sharelink" を設定します。*/

frameNode.className = 'ez-sharelink';

これで、外側の <div> ノードを作成できました。

 

こうして出来上がった "frameNode" の HTML は次のようになります。

<div class="ez-sharelink"></div>

閉じタグまででひとつのノードです。

 

2. 内側 <div> ノードの作成

内側の <div> ノードの作成は、外側のときと同じですね。

/* 内側 div ノードを作成して class="ez-shared-title" を設定します。*/

var titleNode = document.createElement('div');

titleNode.className = 'ez-shared-title';

<div> ノードをひとつ作って "titleNode" 変数に入れ、クラス属性を設定して完成です。

 

2-1.外側 div ノードに内側 div ノードを追加

あるノードを別のノードに追加するには、目的のノードの "appendChild" 関数を使います。

/* 作成した内側 div ノードを外側 div ノードに追加します。*/

frameNode.appendChild(titleNode);

これで frameNode に titleNode を追加できました。

 

ここまでで出来上がった HTML は次の通りです。

<div class="ez-sharelink"><div class="ez-shared-title"></div></div>

だいぶそれらしくなってきました。

 

3. サイトタイトルの取得

サイトタイトルの取得は、最初にやったので簡単ですね。

ただ、今回は取得したタイトルを後で使うので、変数に入れておくことにします。この程度ならわざわざ保存しておくこともないのですけど、練習のつもりでやってみます。

/* 変数 title にサイトタイトルを保存しておきます。*/

var title = document.title;

これで変数 "title" にサイトタイトル (document.title) を入れられたので、これ以降は "title" だけでサイトのタイトルを扱えます。

 

3-1. テキストノードの作成

テキストを HTML として扱うためにテキストノードを作成します。

テキストノードは "document.createTextNode" 関数にテキストを渡すと作成できます。

/* サイトタイトルを持つテキストノードを作成します。*/

var textNode = document.createTextNode(title);

これで、サイトタイトルをテキストに持つテキストノードが出来上がりました。

 

ちなみにここまでで出来上がった textNode の HTML は次のようになっています。

サイトタイトル

テキストのまんまですね。

 

3-2. 内側 div にテキストノードを追加

テキストノードの追加も HTML タグのノードのときと同じです。

/* 内側 div ノードにテキストノードを追加します。*/

titleNode.appendChild(textNode);

これで titleNode に textNode を追加することができました。

 

内側 <div> ノードにテキストノードが追加されて、キャンバス内に出来上がった HTML は次のようになります。

<div class="ez-sharelink"><div class="ez-shared-title">サイトタイトル</div></div>

これで、作ろうとしていた HTML に仕上がりました。

 

4. ノードから HTML を取得

HTML は仕上がったものの、それはまだ DOM 形式になっています。

今回のブックマークレットでは、最終的にはブログに貼る HTML を取得したいので、作成した DOM ノードから HTML を取り出します。

 

ノードから HTML を取得するには、最初のノードの "outerHTML" プロパティを使います。

/* 外側 div ノードから HTML を取得します。*/

var html = frameNode.outerHTML;

これで "frameNode" の HTML を、変数 "html" に入れることができました。

 

これらを組み立てて完成

では、実際にちゃんと採れるか見てみましょう。

これまでの手順を組み立てつつ、最後に "html" をメッセージ表示するコードを追加すると、次のようなコードが出来上がります。

javascript:

(

function()

{

/* 外側 div ノードを作成して class="ez-sharelink" を設定します。*/

var frameNode = document.createElement('div');

frameNode.className = 'ez-sharelink';

 

/* 内側 div ノードを作成し、class="ez-shared-title" を設定します。*/

var titleNode = document.createElement('div');

titleNode.className = 'ez-shared-title';

 

/* 作成した内側 div ノードを外側 div ノードに追加します。*/

frameNode.appendChild(titleNode);

 

/* 変数 title にサイトタイトルを保存しておきます。*/

var title = document.title;

 

/* サイトタイトルを持つテキストノードを作成します。*/

var textNode = document.createTextNode(title);

 

/* 内側 div ノードにテキストノードを追加します。*/

titleNode.appendChild(textNode);

 

/* 外側 div ノードから HTML を取得します。*/

var html = frameNode.outerHTML;

 

/* アラートメッセージで、取得した HTML を表示します。*/

alert(html);

}

)

();

そしてこれをブックマークレットとして登録して、好きなサイトで実行してみると、次のようなテキストを表示させることができました。

ちなみに、実行してもうんともすんとも言わないときは、スクリプトのどこかが間違っているので、がんばって見つけて直します。

サイトの説明文を取得する

サイトに設定されている説明文も取得できます。

説明文は <meta name="description" /> タグに登録されているので、まずはサイト内から <meta> タグを探します。

 

まずは <meta name="description"> を探すことから

全ての <meta> タグを取得するには "document" 全体から "getElementsByTagName" 関数を使って取得するのが簡単です。

/* 全ての meta タグを取得します。*/

var metaNodes = document.getElementsByTagName('meta');

全ての <meta> タグが取得できたら、そこから "name" 属性に "description" が設定されているものを探します。

 

タグをひとつひとつ処理するために必要なループ構文

取得したタグの中からひとつひとつを辿るには "for" 構文を使います。

"for" は、"for (繰返回数をカウントする変数 = 初期値; 継続条件; 繰返時に毎回実行する式)" で指定して、続く { } の中を、継続条件を満たさなくなるまで繰り返し実行します。

 

今回は、それぞれを次のようにすることにします。

繰返回数をカウントする変数 var index
初期値 0
継続条件 index < metaNodes.length
繰返時に毎回実行する式 ++index

継続条件の中の "metaNodes.length" というのは取得できた <meta> タグの数です。"++index" というのは不思議な書き方ですが、変数 index の値を +1 するという意味です。

変数 index が 0 から始まり、継続条件が <meta> タグの数より小さい間、つまり "0 〜 <meta> タグの数 -1" まで繰り返すという意味になります。

 

ちなみに 0 から始めているのは、metaNodes からひとつひとつ取得するのに0 から始まる通し番号で目的のノードを指定するので、その方が都合が良いためです。

たとえば metaNodes の 0 番目(最初)のノードを取得するには "metaNodes[0]" と指定します。"for" での繰り返しと併用すれば "metaNodes[index]" みたいにして順次ノードを取得できます。

 

説明文を探す

探し方は、それぞれのタグの "name" プロパティが "description" であるかを確認して、そうだったらその "content" 属性に設定されているテキストを取得します。

説明文が見つかったら、それ以上は探す必要がないので "break" 命令で "for" ループを抜けておしまいです。

/* 説明文は変数 description に保存します。

見つからなかった時のために、最初に空文字を設定しておきます。*/

var description= '';

 

/* 全ての meta タグをひとつひとつ node 変数に取り出してチェックします。*/

var metaNodes = document.getElementsByTagName('meta');

 

for (var index = 0; index < metaNodes.length; ++index)

{

/* 対象の meta タグをひとつ取り出します。*/

var node = metaNodes[index];

 

/* name 属性に 'description' が設定されているものを探します。*/

if (node.name == 'description')

{

/* 'description' が設定されていたら、

そのタグの 'content' 属性を取得して for ループを終了します。*/

description = node.content;

break;

}

}

これで、変数 "description" にサイトの説明文を取得することができました。

 

生成する HTML に埋め込む

このようにして取得した説明文を、ブックマークレットで作成する HTML に埋め込みます。

作成する HTML としては、サイトタイトルと同じ階層にもうひとつ <div> タグを作って追加する形にしてみます。

<div class="ez-sharelink">

<div class="ez-shared-title">

サイトのタイトル

</div>

<div class="ez-shared-description">

サイトの説明文

</div>

</div>

流れとしては次のようになります。

  1. "<div> ノード" を作成する。(class="ez-shared-description")
  2. "<div> ノード" に "サイト説明文" を追加する。
  3. "外側の <div> ノード" に、作成した "<div> ノード" を追加する。

 

1. div ノードを作成

/* div ノードを作成し、class="ez-shared-description" を設定します。*/

var descriptionNode = document.createElement('div');

descriptionNode.className = 'ez-shared-description';

 

2. div ノードにサイト説明文を追加

/* 取得しておいた description 変数を使ってテキストノードを作成し、

作成した div ノードに追加します。*/

var descriptionTextNode = document.createTextNode(description);

descriptionNode.appendChild(descriptionTextNode);

 

3. 外側 div ノードに、作成した div ノードを追加

/* 作成した div ノードを、外側 div に追加します。*/

frameNode.appendChild(descriptionNode);

既にノードが登録されていた場合、"appendChild" 関数はノードを末尾に追加します。

外側 div ノードには既に <div class="ez-shared-title"> タグが登録されているので、今回追加した <div> タグはそれと同じ階層のその後に登録されます。

 

これらを組み立てて完成

これらを全て組み合わせて、ブックマークレットを完成させます。

新しく増えるスクリプトは HTML を取得する手前に入れ込めば大丈夫です。

javascript:

(

function()

{

/* 外側 div ノードを作成して class="ez-sharelink" を設定します。*/

var frameNode = document.createElement('div');

frameNode.className = 'ez-sharelink';

 

/* 内側 div ノードを作成し、class="ez-shared-title" を設定します。*/

var titleNode = document.createElement('div');

titleNode.className = 'ez-shared-title';

 

/* 作成した内側 div ノードを外側 div ノードに追加します。*/

frameNode.appendChild(titleNode);

 

/* 変数 title にサイトタイトルを保存しておきます。*/

var title = document.title;

 

/* サイトタイトルを持つテキストノードを作成します。*/

var textNode = document.createTextNode(title);

 

/* 内側 div ノードにテキストノードを追加します。*/

titleNode.appendChild(textNode);

 

/* 説明文は変数 description に保存します。

見つからなかった時のために、最初に空文字を設定しておきます。*/

var description= '';

 

/* 全ての meta タグをひとつひとつ node 変数に取り出してチェックします。*/

var metaNodes = document.getElementsByTagName('meta');

 

for (var index = 0; index < metaNodes.length; ++index)

{

/* 対象の meta タグをひとつ取り出します。*/

var node = metaNodes[index];

 

/* name 属性に 'description' が設定されているものを探します。*/

if (node.name == 'description')

{

/* 'description' が設定されていたら、

そのタグの 'content' 属性を取得して for ループを終了します。*/

description = node.content;

break;

}

}

 

/* div ノードを作成し、class="ez-shared-description" を設定します。*/

var descriptionNode = document.createElement('div');

descriptionNode.className = 'ez-shared-description';

 

/* 取得しておいた description 変数を使ってテキストノードを作成し、

作成した div ノードに追加します。*/

var descriptionTextNode = document.createTextNode(description);

descriptionNode.appendChild(descriptionTextNode);

 

/* 作成した div ノードを、外側 div に追加します。*/

frameNode.appendChild(descriptionNode);

 

/* 外側 div ノードから HTML を取得します。*/

var html = frameNode.outerHTML;

 

/* アラートメッセージで、取得した HTML を表示します。*/

alert(html);

}

)

();

これをブックマークレットとして実行すると、タイトルと説明文が含まれた HTML を表示することができました。

サイトタイトルにリンクを追加する。

リンクの共有が目的なので、今のままだとリンクがなくて残念なことになってしまいます。

そこで、サイトタイトルのテキストのところに <a> タグを追加して、クリックすればサイトにジャンプできるようにしてみます。

 

<a> タグを作る

サイトの URL は "location.href" を使って簡単に取得できます。

/* サイト URL を変数 url に取得します。*/

var url = location.href;

これを "<a> タグ" を作成して、その href に設定します。併せて target="_blank" も指定してみます。

/*a タグを作成して、href 属性と target 属性を設定します。*/

var anchorNode = document.createElement('a');

anchorNode.href = url;

anchorNode.target = '_blank';

このノードに、これまでに作成した "サイトタイトル" が格納された textNode を追加します。

/* a タグにサイトタイトルを追加します。*/

anchorNode.appendChild(textNode);

これで、次のような HTML の anchorNode が出来上がりました。

<a href="サイト URL" target="_blank">サイトタイトル</a>

 

サイトタイトルの代わりに <a> タグを追加

これを "titleNode" にノードを追加するときに "サイトタイトル" を追加する代わりにこの "<a> タグ" を追加します。

javascript:

(

function()

{

/* 外側 div ノードを作成して class="ez-sharelink" を設定します。*/

var frameNode = document.createElement('div');

frameNode.className = 'ez-sharelink';

 

/* 内側 div ノードを作成し、class="ez-shared-title" を設定します。*/

var titleNode = document.createElement('div');

titleNode.className = 'ez-shared-title';

 

/* 作成した内側 div ノードを外側 div ノードに追加します。*/

frameNode.appendChild(titleNode);

 

/* 変数 title にサイトタイトルを保存しておきます。*/

var title = document.title;

 

/* サイトタイトルを持つテキストノードを作成します。*/

var textNode = document.createTextNode(title);

 

/* サイト URL を変数 url に取得します。*/

var url = location.href;

 

/*a タグを作成して、href 属性と target 属性を設定します。*/

var anchorNode = document.createElement('a');

anchorNode.href = url;

anchorNode.target = '_blank';

 

/* a タグにサイトタイトルを追加します。*/

anchorNode.appendChild(textNode);

 

/* 内側 div ノードに a ノードを追加します。

textNode を追加していたのから変更です。*/

titleNode.appendChild(anchorNode);

 

/* 説明文は変数 description に保存します。

見つからなかった時のために、最初に空文字を設定しておきます。*/

var description= '';

 

/* 全ての meta タグをひとつひとつ node 変数に取り出してチェックします。*/

var metaNodes = document.getElementsByTagName('meta');

 

for (var index = 0; index < metaNodes.length; ++index)

{

/* 対象の meta タグをひとつ取り出します。*/

var node = metaNodes[index];

 

/* name 属性に 'description' が設定されているものを探します。*/

if (node.name == 'description')

{

/* 'description' が設定されていたら、

そのタグの 'content' 属性を取得して for ループを終了します。*/

description = node.content;

break;

}

}

 

/* div ノードを作成し、class="ez-shared-description" を設定します。*/

var descriptionNode = document.createElement('div');

descriptionNode.className = 'ez-shared-description';

 

/* 取得しておいた description 変数を使ってテキストノードを作成し、

作成した div ノードに追加します。*/

var descriptionTextNode = document.createTextNode(description);

descriptionNode.appendChild(descriptionTextNode);

 

/* 作成した div ノードを、外側 div に追加します。*/

frameNode.appendChild(descriptionNode);

 

/* 外側 div ノードから HTML を取得します。*/

var html = frameNode.outerHTML;

 

/* アラートメッセージで、取得した HTML を表示します。*/

alert(html);

}

)

();

これをブックマークレットで実行すると、サイトタイトルにリンクが貼られた HTML が表示されるようになりました。

出来上がった HTML を貼り付けてみる。

このようにして作成したブックマークレットを使って生成した HTML を張り付けてみると、次のようになりました。

あまりにもシンプルですけど、リンク付きのサイトタイトルはあるし、サイトの説明文も付けられていて、ごくごく最低限ながら、サイトをシェアする目的は果たせていると思います。

サイトのサムネイルとかもつけたいところですけど、時間の都合でひとまず後回しです。

 

あとはこれをスタイルシートで料理してあげれば、見た目がずっと変わってきます。

タグを少しもいじらなくても、スタイルシートを使えばデザインを調整できるからいいですよね。

ちなみに適用してみたスタイルシートはこんな感じです。

div.ez-sharelink

{

width: 600px;

border: 1px #FE9EA5 solid;

background-color: #FCF5EB;

}

 

div.ez-shared-title

{

width: 200px;

height: 88px;

 

text-align: center;

 

float: left;

color: #FFFFFF;

background-color: #FE9EA5;

 

padding: 10px;

}

 

div.ez-shared-title a

{

color: #FFFFFF;

font-weight: bold;

}

 

div.ez-shared-description

{

height: 88px;

color: #EA7F87;

background: #FFFFFF;

 

padding: 10px 10px 10px 230px;

}

スタイルシートを工夫するだけでレイアウトはずいぶん自在に変えられるので、今回みたいな単純な HTML を生成するブックマークレットでも、かなり便利になりそうですね。

良い感じですね!

初めてにしては、なかなかいい具合に仕上がったんじゃないでしょうか。

ブログを運営する上で作れるといいことたくさんありそうですし、コード自体も比較的コンパクトに済みそうなので、もしかすると JavaScript プログラミングの勉強にも丁度いいかもしれません。

 

それにしてもブックマークレットってとっても楽しいしですね。

そんな楽しさを教えてくれた あかめさん に感謝です。

アラートだとテキストをコピーできない場合に備える。

これまでの説明では HTML を出力するのにアラートメッセージを利用してきました。

Mac の Safari 6.0.5 を大前提に作ってきたのでそれで問題はないのですけど、たとえば iPhone の Safari みたいに、アラートメッセージに表示されたテキストをコピーできないような場合に都合が悪かったりします。

そこで、アラートではなく現在表示中のページ上部にテキストとして表示するようにしてみます。

 

コード表示用の div を作る

/* コード表示用 div ノードを作成します。*/

var displayNode = document.createElement('div');

/* 作成した div ノード内のテキストとして、ブックマークレットの HTML を設定します。*/

displayNode.innerText = html;

"innerText" というのは、そのタグの内側のテキストのことです。

これまでは DOM の基本に沿って "createTextNode" と "appendChild" を使ってテキストを設定していましたけど、単純にテキストを持たせたいだけなら、この "innerText" に入れてあげるだけでも簡単に設定できます。

これで、ブックマークレットの HTML をテキストに持つ <div> ノードが作れました。

 

表示位置を決める

作成した <div> ノードを画面に表示させるためには、ブックマークレットを実行したときに表示されていた Web ページに表示させるのが簡単です。

 

表示場所は、今回はページの一番上にしてみます。

画面に表示されているページの一番上というのは <body> タグの直下ですね。

表示されてるページの <body> タグは "document.body" で簡単に取得できるので、ここの 1 番最初の要素として、作成したコード表示用の <div> ノードを挿入します。

 

ノードの挿入には "insertBefore" 関数を使います。

使い方が少し難しいのですが、追加したいノード(今回は document.body) の "insertBefore" 関数を、次の二つの引数を添えて実行します。

  1. "追加するノード"(今回なら displayNode)
  2. "挿入位置にあるノード"(このノードの「前」に挿入される)

今回は <body> の最初の要素として表示したいので、挿入位置はつまり "<body> タグの最初の要素" です。

あるノード内の最初の要素は "firstChild" で取得できるので、今回であれば "document.body.firstChild" ということになります。

 

決めた挿入位置に挿入するには

<div> ノードの表示位置が決まったので、実際に表示してみます。

/* 作成した div ノードを、body の最初の要素として挿入します。*/

document.body.insertBefore(displayNode, document.body.firstChild);

document.body が 2 回もでてきてまどろっこしくなっていますけど、上のコードを見て "<body> タグの最初の要素に displayNode を挿入している" って読めるようになったら、そうとう慣れた証です。

 

表示!

説明が長くなってしまったのでまとめると <body> タグの最初に "コード表示用 <div> ノード" を作って挿入するスクリプトは次のようになりました。

/* コード表示用 div ノードを作成します。*/

var displayNode = document.createElement('div');

 

/* 作成した div ノード内のテキストとして、ブックマークレットの HTML を設定します。*/

displayNode.innerText = html;

 

/* 作成した div ノードを、body の最初の要素として挿入します。*/

document.body.insertBefore(displayNode, document.body.firstChild);

これを、今までの "alert" 関数の代わりに使ってあげれば完成です。

javascript:

(

function()

{

/* 外側 div ノードを作成して class="ez-sharelink" を設定します。*/

var frameNode = document.createElement('div');

frameNode.className = 'ez-sharelink';

 

/* 内側 div ノードを作成し、class="ez-shared-title" を設定します。*/

var titleNode = document.createElement('div');

titleNode.className = 'ez-shared-title';

 

/* 作成した内側 div ノードを外側 div ノードに追加します。*/

frameNode.appendChild(titleNode);

 

/* 変数 title にサイトタイトルを保存しておきます。*/

var title = document.title;

 

/* サイトタイトルを持つテキストノードを作成します。*/

var textNode = document.createTextNode(title);

 

/* サイト URL を変数 url に取得します。*/

var url = location.href;

 

/*a タグを作成して、href 属性と target 属性を設定します。*/

var anchorNode = document.createElement('a');

anchorNode.href = url;

anchorNode.target = '_blank';

 

/* a タグにサイトタイトルを追加します。*/

anchorNode.appendChild(textNode);

 

/* 内側 div ノードに a ノードを追加します。*/

titleNode.appendChild(anchorNode);

 

/* 説明文は変数 description に保存します。

見つからなかった時のために、最初に空文字を設定しておきます。*/

var description= '';

 

/* 全ての meta タグをひとつひとつ node 変数に取り出してチェックします。*/

var metaNodes = document.getElementsByTagName('meta');

 

for (var index = 0; index < metaNodes.length; ++index)

{

/* 対象の meta タグをひとつ取り出します。*/

var node = metaNodes[index];

 

/* name 属性に 'description' が設定されているものを探します。*/

if (node.name == 'description')

{

/* 'description' が設定されていたら、

そのタグの 'content' 属性を取得して for ループを終了します。*/

description = node.content;

break;

}

}

 

/* div ノードを作成し、class="ez-shared-description" を設定します。*/

var descriptionNode = document.createElement('div');

descriptionNode.className = 'ez-shared-description';

 

/* 取得しておいた description 変数を使ってテキストノードを作成し、

作成した div ノードに追加します。*/

var descriptionTextNode = document.createTextNode(description);

descriptionNode.appendChild(descriptionTextNode);

 

/* 作成した div ノードを、外側 div に追加します。*/

frameNode.appendChild(descriptionNode);

 

/* 外側 div ノードから HTML を取得します。*/

var html = frameNode.outerHTML;

 

/* コード表示用 div ノードを作成します。*/

var displayNode = document.createElement('div');

 

/* 作成した div ノード内のテキストとして、ブックマークレットの HTML を設定します。*/

displayNode.innerText = html;

 

/* 作成した div ノードを、body の最初の要素として挿入します。

alert(html) からこれに変更して、ページ上部にコードが表示されるようにします。*/

document.body.insertBefore(displayNode, document.body.firstChild);

}

)

();

これをブックマークレットとして実行すれば、表示中のページの上部に生成したブックマークレットのコードがテキストで表示されるようになりました。

これならきっと大抵のブラウザで、生成したコードをコピーできますね。


[ もどる ]