chrome用の拡張機能を自分が欲しいと思ったので、作ってついでに公開してみました。

ニコニコサムネイル

ニコニコでリンクにマウスオーバーしたらサムネイルが表示されるだけの簡単なものです。
慣れないJavaScriptを勉強しながら作ったので勉強したことをいくつか書き留めておきます。
拡張機能を作成するにはまず manifest.json というファイルを作成します。
今回作った manifest.json はこんな感じ。
{
  "name": "ニコニコサムネイル",
  "version": "1.0.0",
  "description": "ニコニコ動画内のリンクにマウスオーバーでサムネイルを表示します。",
  "icons": {
    "48": "icon_small.png",
	"128": "icon_large.png"
  },
  "content_scripts": [
    {
      "matches": ["http://www.nicovideo.jp/*"],
      "js": ["nico_thumbnail.js"]
    }
  ]
}
この内、上の3つ "name" "version" "description" は必須のようです。
そのまま、拡張機能の名前、バージョン番号、機能の紹介です。
"icons" はアイコンの指定です。同じフォルダの画像を指定してます。
"content_scripts" ではいろいろと設定をします。
 "matches" は拡張機能を働かせるURLを指定しています。ワイルドカードも使えます。
 "js" は拡張機能が呼び出すJavaScriptを指定しています。

manifest.json は拡張機能の設定を記述するので絶対に必要です。
不正な記述があるとアップロードする時に教えてくれます。

拡張機能の構成物として必須なのは manifest.json だけですがそれだけでは何もできないので、他のファイルを作ります。
nico_thumbnail.js が今回の拡張機能の要です。
ソースはこんな感じ。
function NicoThumbnail() {
    var iframeStart = '<iframe width="312" height="176" src="';
    var iframeEnd = '" scrolling="no" style="border:solid 1px #CCC;" frameborder="0" />';
    var watchThumbnailUrl = iframeStart + 'http://ext.nicovideo.jp/thumb/';
    var mylistThumbnailUrl = iframeStart + 'http://ext.nicovideo.jp/thumb_';
    var communityThumbnailUrl = iframeStart + 'http://ext.nicovideo.jp/thumb_community/';
    var seigaThumbnailUrl = iframeStart + 'http://ext.seiga.nicovideo.jp/thumb/';
    
    var thumbnail;
    var isShowed = false;

    this.OnLoadHandler = function (e) {
        elements = document.getElementsByTagName("a");
        for (i = 0; i < elements.length; i++) {
            var text = '';
            if (elements[i].firstChild != null) {
                elements[i].addEventListener("mouseover", obj.OnMouseOverHandler, false);
                elements[i].addEventListener("mouseout", obj.OnMouseOutHandler, false);
            }
        }
    }

    this.OnMouseOverHandler = function (e) {
        createThumbnail(e.target, e.pageX + 5, e.pageY + 5);
    }

    this.OnMouseOutHandler = function (e) {
        if (typeof thumbnail != "undefined" && isShowed) {
            thumbnail.style.display = "none";
            document.body.removeChild(thumbnail);
            isShowed = false;
        }
    }

    function createThumbnail(link, x, y) {
        if (typeof thumbnail != "undefined" && isShowed) {
            thumbnail.style.display = "none";
            doc.body.removeChild(thumbnail);
        }
        thumbnail = document.createElement("div");
        thumbnail.style.position = "absolute";
        thumbnail.style.zIndex = 2147483647;
        thumbnail.style.left = x + "px";
        thumbnail.style.top = y + "px";

        if (link.firstChild != null) {
            var thumbnailUrl = '';
            var id = link.innerText;
            if (id == null) return;
            if (id.match(/^[sn]m[0-9]+$/)) {
                thumbnailUrl = watchThumbnailUrl;
            }
            else if (id.match(/^mylist\/[0-9]+$/)) {
                thumbnailUrl = mylistThumbnailUrl;
            }
            else if (id.match(/^watch\/[0-9]+$/)) {
                thumbnailUrl = watchThumbnailUrl;
                id = id.substring(6);
            }
            else if (id.match(/^im[0-9]+$/)) {
                thumbnailUrl = seigaThumbnailUrl;
            }
            else if (id.match(/^co[0-9]+$/)) {
                thumbnailUrl = communityThumbnailUrl;
            }
            else {
                return;
            }
            thumbnail.innerHTML = thumbnailUrl + id + iframeEnd;
            document.body.appendChild(thumbnail);
            isShowed = true;
        }
    }
}

var obj = new NicoThumbnail();
window.addEventListener("load", obj.OnLoadHandler, false);
大したことはしてないので読んだら大体動きはわかるかなーと思います。

いくつか要所の説明をします。
var obj = new NicoThumbnail();
window.addEventListener("load", obj.OnLoadHandler, false);
new でオブジェクトを作ります。
直に関数を書いていっても問題ないようですが、やっぱりオブジェクト指向に慣れてるもので……
そしてイベントリスナの追加。
要素.addEventListener(イベント名, イベントリスナ, キャプチャをするかどうか?);
って感じですね。
第3引数は説明がめんどくさそうなので他の方のサイトをご参照ください。
addEventListener の第三引数について - hogehoge @teramako 

if (typeof thumbnail != "undefined" && isShowed) {
typeof 要素
で要素の型を調べる。括弧とかピリオドとかじゃなくてスペースで区切ってるだけだとすごく分かりづらい!
ようするに未定義でなく、表示済みであればってことですね。

if (link.firstChild != null) {
    var thumbnailUrl = '';
    var id = link.innerText;
    if (id == null) return;
    if (id.match(/^[sn]m[0-9]+$/)) {
        thumbnailUrl = watchThumbnailUrl;
    }
ソース見返してて気づいたんですけど firstChild 調べてるけど使ってないんですよね。
元々は id に firstChild.nodeValue を代入してたんですけど、リンクの文字列の途中にwbrタグが入ってる奴とかあってうまくいかなかったので innerText に変えてそのままだったのです……
まぁともかく
文字列.match(正規表現パターン)
で文字列がパターンを満たすかを調べます。
パターンの指定は文字列で書くのが自然な気がしますがなぜか直に書いてます……JavaScriptェ……
文字列で何のリンクか判断してそれにあったURLを使います。

そんな感じで必要なファイルが作成できました。
公開する前にはテストをしたいですよね。
作成した拡張機能を読み込むには、Chromeの拡張機能の画面でデベロッパーモードを有効にし 、「パッケージ化されていない拡張機能を読み込む…」を選択して作成したファイルを置いたフォルダを指定します。
ちなみに「拡張機能のパッケージ化」では同じようにフォルダを指定すると crx という拡張子のファイルが作成され、このファイルをChromeで開くと作成した拡張機能を読み込むことができます。
なのでこのcrxファイルを配布すればchromeウェブストアを通さずに拡張機能を公開できます。
個人的な配布とかに使えます。

さてchromeウェブストアに公開する方法です。
chromeウェブストアの右上からデベロッパーダッシュボードに行きます。
そして「新しいアイテムを追加」にいったら後は説明に従って進みます。
この時アップロードするのはCRXファイルではなく拡張機能が入ったフォルダを圧縮したZIPファイルです。
その後説明を入力したりアイコンやスクショやタイルをアップロードしたり と面倒な作業があります。

そして!
chromeウェブストアに何か公開するには5ドルを払わなければいけません。
最初に1回払うだけですがね。
ジャパンネット銀行のワンタイムデビットでも問題なく払えました。 

以上で拡張機能の公開も完了。
良かったら使ってやってください。 → ニコニコサムネイル 
では。