はてなブックマークのタグ検索を行う Ubiquity コマンド作成

注目の FireFox プラグイン Ubiquity の簡単なコマンドを自作してみました。
使用した環境は以下の通り。

Ubiquity コマンドの作成

それでは、はてなブックマークをタグ検索するコマンドを作成します。

まず、はてなブックマークでは以下のような URL にアクセスする事で指定のタグが付与されているブックマークのリストを Atom Feed で取得できるようになっています。

ちなみに、Atom Feed は以下のような形式になります。(今回使用する部分のみ抜粋)

<feed ・・・>
  ・・・
  <entry>
    <id>・・・</id>
    <title>ブックマークのタイトル</title>
    <link type="text/html" rel="related" href="URL"/>
    ・・・
  </entry>
  <entry>
    ・・・
  </entry>
  ・・・
</feed>

そこで、今回作成するコマンドでは Ubiquity のプレビュー画面に Ajax を使ってリアルタイムに取得したブックマークの内容を表示するようにしてみます。(今回はコマンド実行時の処理は実装しません)

まず、以下のような操作を行って Ubiquity の Command Editor 画面を表示します。

  • アドレスバーに about:ubiquity を入力して、「Command Editor」を選択
  • Ubiquity を実行して(Windows なら Ctrl + Spaceキー押下)、command-editor コマンドを実行

Command Editor 画面で「Import Command Template」ボタンを押下し、テンプレートをコマンドの入力エリアに挿入します。
テンプレートを以下のように編集すれば、hatena-book コマンドが使えるようになります。(登録作業等は特に必要ありません)
なお、hatena-book コマンドが使えないようなら、スクリプトの記述に誤りがある可能性が考えられます。

hatena-book.js(0.15版)
CmdUtils.CreateCommand({
  name: "hatena-book",
  icon: "",
  homepage: "http://b.hatena.ne.jp/fits/",
  author: { name: "fits", email: ""},
  license: "GPL",
  description: "はてなブックマークのタグ検索",
  help: "はてなブックマーク",
  takes: {"tag": noun_arb_text},
  //プレビュー時の処理を記述
  preview: function( pblock, input ) {
    if (input.text) {
      var params = jQuery.map(input.text.split(" "), function(item) {
        return "tag=" + item;
      }).join("&");

      CmdUtils.previewAjax(pblock, {
        type: "GET",
        url: "http://b.hatena.ne.jp/fits/atomfeed?" + params,
        dataType: "xml",
        error: function() {
          pblock.innerHTML = "Search Error";
        },
        success: function(responseData) {
          pblock.innerHTML = "Search Success";
          var data = jQuery(responseData);
          var resultHtml = "";

          data.find("entry").each(function(index) {
            var entry = jQuery(this);

            var tempParams = {
              title: entry.find("title").text(),
              url: entry.find("link[rel=related]").attr("href")
            };
            //ログ出力
            //CmdUtils.log(tempParams.title + ", " + tempParams.url);
            var tempHtml = '<div><a href=\"${url}\">${title}</a></div>';
            resultHtml += CmdUtils.renderTemplate(tempHtml, tempParams);
          });
          //プレビュー画面に HTML 書き込み
          pblock.innerHTML = resultHtml;
        }
      });
    }
  },
  //コマンド実行時(Enter キーの押下)の処理を記述
  execute: function(input) {
  }
});

上記スクリプトの作成に使った Ubiquity コマンド作成の注目点は以下の通り。

  • プレビュー画面の処理は preview 関数に記述
    • pblock 引数に HTML を書き込む事でプレビュー画面を変更
    • input 引数で入力値を取得
  • コマンド実行時の処理は execute 関数に記述
  • takes で引数の表示名と型を指定
  • jQuery が使用できる
  • CmdUtils.previewAjax で Ajax を処理
    • success に成功時の処理を記述
    • error にエラー発生時の処理を記述
  • CmdUtils.log(ログ内容) で FireBug のコンソールにログを出力
  • CmdUtils.renderTemplate(テンプレート文字列, パラメータ) で "${変数名}" を使ったテンプレート処理が可能

Ubiquity を実行し、以下のように hatena-book コマンドに引数を与えてやるとブックマークのリストが表示され、ブックマークをクリックするとそのページが開きます。

Ubiquity 0.5 対応版

Ubiquity 0.5 からコマンドの記述方法が少し変更になったので、0.5 対応版を記載しておく。
変更は以下の通り。

  • name が names に変更
  • takes が arguments に変更
hatena-book.js(0.54版)
CmdUtils.CreateCommand({
  names: ["hatena-book"],
  icon: "",
  homepage: "http://b.hatena.ne.jp/fits/",
  author: { name: "fits", email: ""},
  license: "GPL",
  description: "はてなブックマークのタグ検索",
  help: "はてなブックマーク",
  arguments: [{role: 'object', nountype: noun_arb_text}],
  preview: function( pblock, arguments ) {
    //0.15用のソースをそのまま使うための措置
    arguments.text = arguments.object.text;
    if (arguments.text) {
      var params = jQuery.map(arguments.text.split(" "), function(item) {
        return "tag=" + item;
      }).join("&");

      //パラメータのログ出力
      CmdUtils.log(params);

      CmdUtils.previewAjax(pblock, {
        type: "GET",
        url: "http://b.hatena.ne.jp/fits/atomfeed?" + params,
        dataType: "xml",
        error: function() {
          pblock.innerHTML = "Search Error";
        },
        success: function(responseData) {
          pblock.innerHTML = "Search Success";

          var data = jQuery(responseData);
          var resultHtml = "";

          data.find("entry").each(function(index) {
            var entry = jQuery(this);

            var tempParams = {
              title: entry.find("title").text(),
              url: entry.find("link[rel=related]").attr("href")
            };

            //ログ出力
            //CmdUtils.log(tempParams.title + ", " + tempParams.url);

            var tempHtml = '<div><a href=\"${url}\">${title}</a></div>';
            resultHtml += CmdUtils.renderTemplate(tempHtml, tempParams);
          });

          pblock.innerHTML = resultHtml;
        }
      });
    }
  },
  execute: function(arguments) {
  }
});