2009/01/05

Safari で選択語によるサイト内検索する Bookmarklet (Safari の getSelection の挙動)

Tiger マシンが家に 1台あるのですが、この度、ようやく Mac OS X v.10.4.10 から 10.4.11 にアップデートしました。10.4.11 にしていなかったのは、ひとえに 10.4.11 により Safari 3 に移行すると、AcidSearch が使えなくなってしまうという理由によるものです1

Safari の組み込み検索フィールドを拡張する

AcidSearch のように Safari の検索ボックスを拡張するプラグインの代替としては以下のようなものがあります。

  • Yahoo! に買収された Inquisitor
  • 検索ボックスの拡張に留まらない多機能プラグイン Glims

Safari の Google 検索窓ではなく、Firefox のスマートキーワードのようなアドレスバーからの検索なら、以下のようなプラグインがあります。

  • これまた Safari 使いには欠かせない多機能プラグイン SafariStand
  • 単機能なら Keyurl(現在、サイトにつながりません…)

Google のサイト内検索を簡単にしたい

前置きが長くなりましたが、上記に紹介したような AcidSearch 代替プラグインでは、どうしてもできないことがあります。サイト検索です2。私はサイト内検索をすることが多いので、これができないとどうしても効率に不満が残ります。AcidSearch はサイト内検索ができたので、よかったのです。

いろいろ調べてみたのですが、現在、Safari のプラグインでこのサイト検索ができるものはなさそうです。Firefox や IE なら Google ツールバーを使う方法もあるのですが…。

サイト内検索をするブックマークレット

しかたないので、サイト内検索は Bookmarklet で実現することにしました。もう既に誰かが同様のものを作っていそうなきもしますが、以下で公開しておきます。

javascript:l=location.hostname;k='%22'+encodeURIComponent(window.getSelection())+'%22';window.location='http://www.google.com/search?as_q='+k+'&as_sitesearch='+l;

使い方は、下記のリンクをブックマークしておいて、必要なときに呼び出すだけです。選択した単語部分をそのとき開いているサイト内で Google のサイト検索を用いて検索結果を表示します。

検索結果は同一ウインドウで開きますが、新規ウインドウで開きたい場合は、window.location の部分を window.open にすればいけると思います。

この Bookmarklet をブックマークバーの一番左に置いておけば、⌘1 (cmd+1) で一発でサイト内検索を行うこともできます3

Safari の window.getSelection() の挙動

このブックマークレットを作るにあたって、ちょっとハマったのが、Safari の window.getSelection() の動作でした。

Safari では window.getSelection() はオブジェクトとして返ってくるのですが、それを例えば window.getSelection().toString() としても、テキストが得られないようなのです。

プロパティを調べると、toString:[function] が定義されていることもわかる(toStringしか定義されていないこともわかる)。しかし、s.toString()=undefined なのだ。alert(s) とすれば、選択された文字列が表示されるので、toString()は実装されているように思うのだが。。。

いろいろ調べてみたのですが、WebKit Bugzilla #46094 なんかを見てみると、toString は Firefox と同様に動くようになったと書いてあります。ただ、上記の記事が 2007年 4月、#4609 の Fix は 2006年 1月なので、直っていてよさそうなものなのですが、Safari 3 になるまで修正が入らなかったのかもしれません。

この問題があったときに、回避策として window.getSelection() をテキストにする方法は、検索するといくつかでてきました。

  • str=window.getSelection()+'';
  • str=unescape(escape(window.getSelection()));

前者は、空のストリングを付加して、window.getSelection() の返すオブジェクトをテキストに変えているようです。

後者も似たようなものですが、私が公開している Title+URI+Text.scpt で使っている方法です5

そんなわけで、以下のようなコードを書いてみました。

javascript:l=location.hostname;k=window.getSelection();k='%22'+k+'%22';window.location='http://www.google.com/search?as_q='+k+'&as_sitesearch='+l;

これでうまく動くような感じだったのですが、落とし穴がありました。このコードだと、取得した文字列が元のページの文字コードに依存する形になり、文字列を Google に渡したときに元のページの文字コードに基づいて URI エンコードした形で URL に検索クエリが入ってしまうのです。UTF-8、Shift_JIS のページでは問題なく動いたのですが、EUC-JP のページではクエリが文字化けしてしまうことが判明しました。

どうしたものかなーと思ったのですが、ページから取得した文字列を encodeURIComponent したところ、UTF-8 で URI エンコードされた文字列になったので、めでたく動くようになりました。

というわけで、簡単かと思いきや、意外に手数をかけてしまいました。


  1. 当初はそれ以外にも Safari 3 非対応プラグインが多かったのでアップデートをためらっていたのですが、ほとんどが Safari 3 対応、もしくは別の代替手段が出てきたために、AcidSearch が私には最後の障害となっていました。 

  2. Bookmarklet に限らず、Safari のブックマークバーに登録されているブックマークは左から順番に (cmd) + 数字 のキーボードショートカットが割り振られています。 

  3. Bug 4609 - window.getSelection().toString() is undefined (range object returned from window.getSelection() is useless) 

  4. window.getSelection() で AppleScript から Safari の選択テキストが取得できなくなったために採用した方法なのですが、なんでこうする必要があるのかという背景は今回知りました。 

ポスト @ 1:00:53 , 修正 @ 2009/06/01 1:28:13 | , , , | 「このエントリーを含むはてなブックマーク」ボタン この記事「Safari で選択語によるサイト内検索する Bookmarklet (Safari の getSelection の挙動)」を含むはてなブックマークの数

Comment

No Comments

Post Your Comment



(Smile) (Wink) (Laugh) (Foot in mouth) (Frown) (Gasp) (Cool) (Tongue)

*は入力必須です。E-Mailは公開されません。