10/29/2010

Facebook に登録してみた

Facebook にとりあえず登録だけしてみた。使い方をよく見ていないので、あまり書くことはないけど、登録で生年月日を選ぶときに少し驚いた。

年のセレクトボックスは 1905 年から選べる。1905 年て。今 105 歳やんか。105 歳が Facebook するってなかなか想像し難い。1900 年ではいけなかったんだろうか。なんか中途半端だし。

全日本女子バレーボールは強いなぁ

世界バレーが始まって、昨日録画しておいたポーランド戦を今見たけど、昔に比べて随分と強くなったなぁ。私が高校の時くらいから見てきたけど、今が一番強いんじゃないだろうか。

なんと言っても竹下が凄過ぎる。世界最高のセッターというのは伊達じゃない。リベロの佐野も同じく凄過ぎる。逆に、この二人が抜けたとき、どうなってしまうんだろうかと、ちょっと不安。

goSearchForYou をリニューアルしてみた

先日アップデートした goSearchForYou をバージョン 2 にリニューアルしてみた。

主な変更点は次の通り。
  • 表示方法を F12(OPTION 画面では F1〜F12 まで変更可)、Shift キーを押しながらのクリックへ変更
  • 非表示方法の変更(検索ボックスから離れた位置でのクリックへ変更)
  • コンテクストメニューの廃止
  • 左上の固定場所からカーソルの近くでの表示へ変更
  • OPTION 画面の独立化
今までは出現場所が左上に固定だったけど、カーソルの近くに表示させたり、ショートカットキーもファンクションキー単体で使えるようにしたり、隠す場合も検索ボックスから離れたところをクリックする、というように利便性を図ってみた。また、ちょっと狭かった OPTION 画面も全画面表示としたので、見やすくなったかな・・・とは思う。

ついでにスクリーンショットも貼ってみる。

検索ボックスはこんな感じ。


オプション画面


文字を選択した上での呼び出しはこんな感じ。


良かったら、下記からどうぞ。

Chrome Extensions:
goSearchForYou - Google Chrome 拡張機能ギャラリー

Safari Extensions:
goSearchForYou | Prime Design Works | Webサイト制作・開発 | 京都市内・京都府

10/22/2010

Safari Extension "previewForBlogger" がアップル公式ギャラリーに載りました

結構ダメだろうなと思っていたし、こんなことを言ってはいけないんだろうけど、審査に通ると思ってなかった。ギャラリーは英語版しかないし、掲載されているのは海外企業が占めているし、しがない SOHO が作った機能拡張など、、、と思っていたけど、載せてくれた。

Apple - Safari - Safari Extensions Gallery

10/20/2010

goSearchForYou に新しい機能を搭載してみた

昨日公開した goSearchForYou に新しい機能を加えてみた。

ブラウザ内でテキストを選択した状態で、ショートカットキーで goSearchForYou を呼び出すと、その選択したテキストが入力ボックスに反映される、という機能。これはかつての先輩からご提案いただいた。ありがとうございます。

なお、これは Safari/Chrome Extensions に限っての機能で、Widget 版には実装していません。

良かったら、下記からどうぞ。

Chrome Extensions:
goSearchForYou - Google Chrome 拡張機能ギャラリー

Safari Extensions:
goSearchForYou | Prime Design Works | Webサイト制作・開発 | 京都市内・京都府

Apple Dashboard Widget:
goSearchForYou | Prime Design Works | Webサイト制作・開発 | 京都市内・京都府

10/19/2010

Safari/Chrome Extension / Apple Dashboard Widget "goSearchForYou" を公開してみた

なにかを検索するとき、いちいちそのウェブサイトに行き、検索しなければならない。Google 検索などはブラウザに検索ボックスが仕込まれてはいるけど。

で、色々な検索を一つの検索ボックスにまとめる機能拡張を Safari 用と Chrome 用に作ってみた。ショートカットキーや右クリックによるコンテクストメニューで呼び出せ、引っ込ませることができる。

それに、セレクトボックス内は、検索した頻度を計算し、よく使うものから順に並べるようにしているので、人によっては便利に感じる、、、かもしれない。

あと、普通に Return キーもしくは Enter キーもしくはボタンのクリックで検索すると、同じウィンドウに、十字キーの「↑」を一緒に押すと新しいタブで検索できるようにしている。

検索できる web service は以下の通り。
  • Google検索
  • Google画像検索
  • Google地図検索
  • Googleニューズ検索
  • Googleブログ検索
  • YouTube動画検索
  • iTunesストア検索
  • Wikipedia検索
  • amazon商品検索
  • 駅探乗り換え検索
  • livedoor天気検索
  • Ustreamライヴ検索
  • Goo郵便番号検索
  • Goo国語辞書検索
  • Goo英和辞書検索
  • Goo和英辞書検索
  • Goo車検索
  • Gooバイク検索
  • はてなブックマーク検索
  • はてなダイアリー検索
  • 食べログ検索
  • ぐるなび検索
  • じゃらん宿泊検索
  • チケットぴあ検索
  • QLife病院検索
  • クックパッド レシピ検索
  • Twitter検索
  • Vectorソフト検索
  • W3C Validator
  • 価格.com商品検索
  • ヨドバシカメラ商品検索
  • 楽天市場検索
  • 楽天オークション検索
  • Yahoo!ショッピング商品検索
  • Yahoo!オークション商品検索
  • アメーバ ブログ検索

良かったら、下記からどうぞ。

Chrome Extensions:
goSearchForYou - Google Chrome 拡張機能ギャラリー

Safari Extensions:
goSearchForYou | Prime Design Works | Webサイト制作・開発 | 京都市内・京都府

Apple Dashboard Widget:
goSearchForYou | Prime Design Works | Webサイト制作・開発 | 京都市内・京都府

10/16/2010

ウェブページに iframe があって複数挿入されてしまう場合の対処 [Chrome Extensions を作ってみる:第九回]

Safari Extensions の場合 と同じように、読み込んだウェブページに iframe があった場合に、iframe 内の html 以下にも挿入されてしまう。

そこで、同じように content_scripts と background_page の url のやり取りで解消する。

★content_scripts
chrome.extension.sendRequest({action: "getURLofTab",}, function(rcv) {
  if (location.href == rcv) // 次の処理
});

★background_page 内の Javascript
function chkURL(req, sender, callback) {
  chrome.windows.getCurrent(function(w) {
    chrome.tabs.getSelected(w.id, function(t) {
      callback(t.url);
    });
  });
}
chrome.extension.onRequest.addListener(chkURL);

これも、manifest.json 内にタブを操作する記述を加えないといけない。

★manifest.json
...
"permissions": ["tabs"],
...

開いている全てのタブに処理を走らせる [Chrome Extensions を作ってみる:第八回]

Safari Extensions の場合 と同様に、読み込んだページに挿入したでユーザーが変更した場合、有効なのは操作しているタブに限られてしまう。そこで、ユーザーが設定を保存するタイミングで、開いている全てのタブに処理を走らせ、設定の同期を行う必要が出てくる。

記述は Safari Extension よりも長くなるけど、同じように全てのウィンドウを取得し、タブを取得し、それぞれに処理を走らせることができる。

以下は、background_page から全てのタブに chgSettings の処理を走らせる場合。

★background_page 内の Javascript
// 全てのウィンドウを取得する
chrome.windows.getAll({populate: true}, function(windows) {
  for (var w in windows) {
// 全てのタブを取得する
    var tabs = windows[w].tabs;
    for (var t in tabs) {
      chrome.tabs.sendRequest(tabs[t].id, {action: "chgSettings", text: "xxx"});
    }
  }
});

ちなみに、manifest.json 内にタブを操作する記述を加えないといけない。

★manifest.json
...
"permissions": ["tabs"],
...

独自のコンテクストメニューを生成する [Chrome Extensions を作ってみる:第七回]

Chrome 6 以降は、独自のコンテクストメニューを生成することができる。Safari Extensions の場合 とは違い、manifest.json と background_page で生成する。

下記は、コンテクストメニューに「test」と表示させ、これがクリックされたら、「recieved」とアラートを出す例。

★manifest.json
...
"permissions": ["contextMenus"],
...

★background_page
function fromContext() {
  alert("received");
}
chrome.contextMenus.create({title: "test", onclick: fromContext});

独自の要素からページ遷移を行う [Chrome Extensions を作ってみる:第六回]

Safari Extensions の場合 と同様に、Chrome Extensions でも form 要素でかつ、action や onsubmit で Javascript からページ遷移をしたい場合、content_scripts だけでは遷移できない。background_page も使ってページ遷移をさせる必要がある。

ただ、Chrome Extensions では、manifest.json にタブの操作を許可する記述を加えないといけない。

★manifest.json
...
"permissions": ["tabs"],
...

下記は Safari Extensions の場合と同様に、独自の form 要素の onsubmit で sendUrl() を指定し、その結果、入力ボックスで指定された URL にページ遷移を行う場合。

★content_scripts
// form 要素を挿入する
var testForm = document.createElement("form");
testForm.onsubmit = "test";
testForm.method = "post";
document.body.insertBefore(testForm, document.body.firstChild);
testForm.addEventListener("submit", sendUrl); // addEventListener で処理先を指定
// 入力ボックスを上記の testForm に生成する
var testInput = document.createElement("input");
testInput.type = "text";
testInput.id = "testInput";
testInput.name = "testInput";
testForm.appendChild(testInput);
// ボタンを上記の testForm に生成する
var testSubmit = document.createElement("input");
testSubmit.type = "submit";
testSubmit.value = "send";
testForm.appendChild(testSubmit);

// submit で送られてきた処理
function sendUrl() {
  chrome.extension.sendRequest({action: "open", text: testInput.value});
}

★background_page 内の Javascript
function GoTo(req, sender, callback) {
// 新規タブで開く場合
  chrome.tabs.create({url: req.text, selected: false});
// 同じタブで開く場合
  chrome.windows.getCurrent(function(w) {
    chrome.tabs.getSelected(w.id, function(t) {
      chrome.tabs.update(t.id, {url: req.text});
    });
  });
}
// content_scripts からの受信
  chrome.extension.onRequest.addListener(GoTo);

ちなみに、url に日本語が含まれる場合、このままでは遷移できないので、上記の sendUrl() 内の testInput.value をエンコードしてやる必要がある。
function sendUrl() {
  chrome.extension.sendRequest({action: "open", text: encodeURI(testInput.value)});
}

10/12/2010

content_scripts と background_page でデータをやり取りする [Chrome Extensions を作ってみる:第五回]

Safari Extensions での「スクリプト」と「グローバルページ」でデータをやり取りするように、Chrome Extension でもやり取りが当然できる。しかも Safari Extensions よりも簡単にできる。

★content_scripts
// 変数 msg に "send" を格納
var msg = "send";
// sendRequest で background_page に送信
chrome.extension.sendRequest({action: "chgMsg", text: msg}, function(rcv) {
// function(rcv) がコールバックとして受信時に発動
  getMsg(rcv);
});
// コールバック受信により発動
function getMsg(afterMsg) {
  alert("after:" + afterMsg);
}

★background_page 内の Javascript
// request には action と text が格納されている
function getMessages(request, sender, callback) {
// コールバック用としての callback に返信用として "received" を格納
  if (request.action == "chgMsg") callback("received");
}
// content_scripts での sendRequest を受信
chrome.extension.onRequest.addListener(getMessages);

結果、「after:recieved」という文字列がアラートとして表示される。

読み込んだウェブページに CSS を適用させる [Chrome Extensions を作ってみる:第四回]

Safari Extensions の場合もやったことを、Chrome Extensions でもやってみる。

これは、Apple の背景を青にしてみるという例。

★manifest.json
{
  "content_scripts": [{
    "css": [ "apple.css" ],
    "matches": ["http://www.apple.com/*"],
    "run_at": "document_end"
  }],
  "name": "test",
  "version": "1.0.0.0"
}

★apple.css(content_scripts)
body {background: rgba(0, 102, 255, .7) !important;}

これだけで、実現できる。

読み込んだウェブページの内容を使って処理を行う [Chrome Extensions を作ってみる:第三回]

Safari Extensions の場合もやったことを、Chrome Extensions でもやってみる。

これは、Apple のトップページ右上にある検索ボックスに「Safari Extensions」という文字を放り込むような処理を作ってみるという例。

★manifest.json
{
  "content_scripts": [{
    "js": [ "apple.js" ],
    "matches": ["http://www.apple.com/*"],
    "run_at": "document_end"
  }],
  "name": "test",
  "version": "1.0.0.0"
}

★apple.js(content_scripts)
document.getElementById("sp-searchtext").value = "Chrome Extensions";

これだけで、実現できる。

Extension の定義ファイル [Chrome Extensions を作ってみる:第二回]

Safari Extension の場合「機能拡張ビルダー」で設定できるが、Chrome Extension の場合は「manifest.json」に記述するみたい。

備忘録として、下記に書き方を残しておこうと思う。とりあえず実際に自分が使ったものを記述するけど、今後も追加していく予定。

{
// ウェブページ内で動作するファイルを定義
  "content_scripts": [{
// 読み込む Javascript
    "js": [ "js/injected.js" ],
// 読み込む CSS
    "css": [ "css/injected.css" ],
// 動作する対象のドメイン等。「*」によるワイルドカードも使える
    "matches": ["http://*/*"],
// 動作するタイミング(オプションは、document_idle(デフォルト値)、document_end、document_idle
    "run_at": "document_end"
  }],
// ギャラリーに公開される説明文
  "description": "この機能拡張の説明",
// 表示されるアイコン。種類別に定義できる
  "icons": {
    "128": "icon128.png",
    "16": "icon16.png",
    "32": "icon32.png",
    "48": "icon48.png"
  },
// 機能拡張の名前
  "name": "ExtensionName",
// バックグラウンドで動かす html
  "background_page": "background.html",
// パーミッション
// tabs: 他のタブを操作したりするのに必要
// contextMenus: コンテクストメニューに項目を作ったりするのに必要(Chrome 6 以上)
  "permissions": ["tabs", "contextMenus"],
// version 表記
  "version": "1.0.0.0"
}

10/09/2010

Safari/Chrome Extension "previewForBlogger" を公開してみた

前に、Blogger の新しい投稿画面がイマイチ というエントリーで書いたけど、Blogger が新しい UI にしてからというもの、プレビューをするのが面倒だった。いちいち新しいウィンドウが開いてしまうので、初めはなにがなんだか判らなくなってしまう。Google Product Ideas に投稿はしたけど、改造されるような感じもないので、機能拡張として作ってみた。

これは入力しているテキストエリアの下にプレビューが表示されるようにしているので、いちいちウィンドウを開かなくてもいい。あと、「ラベル」の入力エリアがなんか新 UI では非常に狭くなったので、広げてみた。

良かったら、下記からどうぞ。

Chrome:
previewForBlogger - Google Chrome 拡張機能ギャラリー
Safari:
previewForBlogger | Prime Design Works | Webサイト制作・開発 | 京都市内・京都府

10/07/2010

Safari Extension "noticeAboutMe" の公開場所を Google サイトにした

どうも私が契約しているレンタルサーバーでは、.htaccess によるファイルタイプの追加ができない。エラーになってしまう。そもそも、「配布」を許していないらしく、ポリシー的にも現実的にも無理。

そこで、Google がサーバースペースとか供給してないかと思って見てみると、「Google サイト」というのがやっぱりあった。で、自前でウェブサイトを持っている身としては別に「Google サイト」上で構築する必要はないので、早速ファイルをアップロードできないかを色々クリックしてみると、やっぱりあった。

試しに Safari Extensions のファイルである .safariextz を置いてみる。ダウンロードしてみる。でけた。一応、利用規約とかも読んでみたけど、ポルノやら悪意あるファイルでなければ置けるっぽい、というかこういう置いてはダメという記述が見当たらない(ポルノやら悪意あるファイルは置いちゃダメってのは、もちろん書いてある)ので、とりあえずここに置いておこう。

ということで、Twitter の mentioning(@ ユーザー ID で発言された tweet)や Direct Message、Retweet があった場合にお知らせする noticeAboutMe の Safari 版も、ちゃんとダウンロードできるようになりました。

noticeAboutMe | Prime Design Works | Webサイト制作・開発 | 京都市内・京都府

ウェブページに iframe があって複数挿入されてしまう場合の対処 [Safari Extensions を作ってみる:第十三回]

読み込んだページに独自の要素を表示させる のエントリーで書いたような形では、読み込んだウェブページに iframe があった場合に、iframe 内の html 以下にも挿入されてしまい、実に困ってしまう。そんな筈じゃないのに、って思うが仕方ない。これはかなり悩んだ。むしろ、悶絶した。

ということで、「グローバルページ」で指定した html(もしくは、その html 内で指定している Javascript)で、そのタブの url を取得し、「スクリプトを終了」で指定した Javascript に送り、その Javascript で自身の url を取得し、比較して処理するかどうかを判断すれば、iframe 内の html 以下に挿入されることはなくなる。

★「スクリプトを終了」で指定した Javascript
function cmpURL(evt) {
  if (location.href == evt.message) 次の処理;
}
// 「グローバルページ」で指定した html へ送信
safari.self.tab.dispatchMessage("getURLofTab", "");
// 「グローバルページ」で指定した html からの答えを受信
safari.self.addEventListener("message", cmpURL, false);


★「グローバルページ」で指定した html 内の Javascript
function getInfo(evt) {
  var URLofTab = safari.application.activeBrowserWindow.activeTab.url;
  safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("answer", URLofTab);
}
safari.application.addEventListener("message", getInfo, false);

10/05/2010

設定内容の保存先には localStorage がいいと思う [Safari Extensions を作ってみる:第十二回]

「機能拡張ビルダー」の一番下にある「機能拡張の設定」では「非表示(input の type="hidden")」として、ユーザーに変更させたくない項目を保存したりできるけど、例えばバグ改修などでアップデートした場合、ユーザーがインストールするとこの「機能拡張の設定」の情報に上書きされてしまう。

そこで、localStorage の出番が来る。「機能拡張ビルダー」の「スクリプトを終了」で指定した Javascript 内で localStorage を使ってしまうと、その表示しているウェブページの storage になってしまうので、「グローバルページ」で指定した html(もしくは、その html 内で指定している Javascript)内で localStorage を使う。すると、Extension の storage としてコンピュータに保存される。

ということで、「機能拡張ビルダー」内の設定情報は、localStorage がなかった場合にのみ(初めてのインストール、もしくは未使用状態、など)取得すれば良く、その他は localStorage の情報で処理すれば良いと思う。

例えば、「sample」という情報を「key」をいう storage に保存する場合は、こんな感じ。

★保存する場合(「グローバルページ」で指定した html 内の Javascript)
localStorage.setItem("key", "sample");

逆に、localStorage に情報がないときには「機能拡張ビルダー」の「機能拡張の設定」から、情報があるときは localStorage から、thisKey という変数に突っ込む場合はこんな感じ。

★取得する場合(「グローバルページ」で指定した html 内の Javascript)
if (localStorage.setItem.key) {
  var thisKey = localStorage.getItem("key");
} else {
  var thisKey = safari.extension.settings.getItem("key");
}

開いている全てのタブに処理を走らせる [Safari Extensions を作ってみる:第十一回]

「機能拡張ビルダー」の一番下に「機能拡張の設定」という項目があるけど、レイアウトを自由にはできないので、場合により美しくないレイアウトになってしまう。そこで、読み込んだページに独自の要素で設定画面を設けることもあるけど、その設定画面でユーザーが変更した場合、有効なのは操作しているタブに限られてしまう。そこで、ユーザーが設定を保存するタイミングで、開いている全てのタブに処理を走らせ、設定の同期を行う必要が出てくる。

Safari Extensions では、「グローバルページ」で記述した Javascript であれば、開いているウィンドウやタブの枚数を取得し、それぞれをターゲットにして処理を走らせることができる。

以下は、グローバルページから全てのタブに chgSettings の処理を走らせる場合。

★「グローバルページ」で指定した html 内の Javascript
<!doctype html>
<html lang="en">
<head>
<script type="text/javascript">
// 記述が長くなるので、with() でまとめる
  with (safari.application) {
// browserWindows では開いているウィンドウの枚数が判別できる
    for (var w = 0; w < browserWindows.length; w++) {
// tabs では開いているタブの枚数を判別できる
      for (var t = 0; t < browserWindows[w].tabs.length; t++) {
        tabs[t].page.dispatchMessage("chgSettings", settingValues);
      }
    }
  }
</script>
</head>
<body></body>
</html>

独自のコンテクストメニューを生成する [Safari Extensions を作ってみる:第十回]

Safari Extensions では、右クリック時に表示されるコンテクストメニューに独自のメニューを追加できる。

新規のコンテクストメニュー名が「ページタイトルを表示」とし、クリックされた場合に、そのページのタイトルをアラート表示する、という場合はこんな感じ。メニューの生成は「機能拡張ビルダー」で、メニューがクリックされた場合の処理は「グローバルページ」に記述する。

★機能拡張ビルダーでの指定
  1. 「機能拡張ビルダー」の「機能拡張クローム」内「コンテクストメニュー項目」右のボタンをクリックする
  2. 「タイトル」にメニューに「ページタイトルを表示」と入力する
  3. 「識別子」と「コマンド」に「showTitle」と入力する(「コマンド」を省略した場合、「識別子」と同じとして扱われるので、「識別子」と同じ名称でも問題はない)

★「グローバルページ」で指定した html 内の Javascript
<!doctype html>
<html lang="en">
<head>
<script type="text/javascript">
  function fromContext(evt) {
    if (evt.command === "showTitle") {
// タイトルをアラート表示
      alert(safari.application.activeBrowserWindow.activeTab.title);
    }
  }
// コンテクストメニューがクリックされた場合
  safari.application.addEventListener("command", fromContext, false);
</script>
</head>
<body></body>
</html>

独自の要素からページ遷移を行う [Safari Extensions を作ってみる:第九回]

読み込んだページに独自の要素を表示させ、これが form 要素でかつ、action や onsubmit で Javascript からページ遷移をしたい場合、この独自の要素を挿入している「スクリプトを終了」で指定した Javascript だけでは遷移できない。これは「グローバルページ」を使うことにより、同じタブでのページ遷移や新規タブでのページ遷移を行うことができる。

独自の form 要素の onsubmit で sendUrl() を指定し、その結果、入力ボックスで指定された URL にページ遷移を行う場合はこんな感じ。もちろん、チェック等の処理は必要不可欠ではあるけど、今回は省略したいと思う。

★「スクリプトを終了」で指定した Javascript
// form 要素を挿入する
var testForm = document.createElement("form");
testForm.onsubmit = "test";
testForm.method = "post";
document.body.insertBefore(testForm, document.body.firstChild);
testForm.addEventListener("submit", sendUrl); // addEventListener で処理先を指定
// 入力ボックスを上記の testForm に生成する
var testInput = document.createElement("input");
testInput.type = "text";
testInput.id = "testInput";
testInput.name = "testInput";
testForm.appendChild(testInput);
// ボタンを上記の testForm に生成する
var testSubmit = document.createElement("input");
testSubmit.type = "submit";
testSubmit.value = "send";
testForm.appendChild(testSubmit);

// submit で送られてきた処理
function sendUrl() {
  safari.self.tab.dispatchMessage("open", testInput.value);
}

★「グローバルページ」で指定した html 内の Javascript
<!doctype html>
<html lang="en">
<head>
<script type="text/javascript">
  function GoTo(evt) {
// 新規タブで開く場合
    safari.application.activeBrowserWindow.openTab().url = evt.message;
// 同じタブで開く場合
    safari.application.activeBrowserWindow.activeTab.url = evt.message;
  }
// content_scripts からの受信
  safari.application.addEventListener("message", GoTo, false);
</script>
</head>
<body></body>
</html>

ちなみに、url に日本語が含まれる場合、このままでは遷移できないので、上記の sendUrl() 内の testInput.value をエンコードしてやる必要がある。
function sendUrl() {
    safari.self.tab.dispatchMessage("open", encodeURI(testInput.value));
}

読み込んだページに独自の要素を表示させる [Safari Extensions を作ってみる:第八回]

Safari Extensions を作っていくにあたり、読み込んだページに独自の要素を表示させたい場合は、「機能拡張ビルダー」の「スクリプトを終了」の項目に Javascript を指定し、その中で操作することができる。

とりあえず、「<p>test</p>」を表示してみるときはこんな感じで。

★test.js
var test = document.createElement("p");
test.textContent = "test";
document.body.insertBefore(test, document.body.firstChild);

あとはこれに css で position: absolute; などで整形していけば、既存のページの見た目を害せずに表示することができる。