<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:admin="http://webns.net/mvcb/"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Travellers Tales</title>
<link>http://travel-lab.info/tech/pblog/index.php</link>
<pubDate>Mon, 05 Jan 2009 01:00:53 +0900</pubDate>
<description>
Travellers Tales - RSS 2.0 (Really Simple Syndication).
</description>
<item>
<title>Safari で選択語によるサイト内検索する Bookmarklet (Safari の getSelection の挙動)</title>
<link>http://travel-lab.info/tech/pblog/article.php?id=200</link>
<guid>http://travel-lab.info/tech/pblog/article.php?id=200</guid>
<pubDate>Mon, 05 Jan 2009 01:00:53 +0900</pubDate>
<description>Tiger マシンが家に 1台あるのですが、この度、ようやく Mac OS X v.10.4.10 から 10.4.11 にアップデートしました。10.4.11 にしていなかったのは、ひとえに 10.4.11 により Safari 3 に移...</description>
<content:encoded>
<![CDATA[<p>Tiger マシンが家に 1台あるのですが、この度、ようやく Mac OS X v.10.4.10 から 10.4.11 にアップデートしました。10.4.11 にしていなかったのは、ひとえに 10.4.11 により Safari 3 に移行すると、<a href="http://www.pozytron.com/archives/2007/11/acidsearch_07b3.html" title="pozytron: news: AcidSearch 0.7b3">AcidSearch</a> が使えなくなってしまうという理由によるものです<sup id="fnref:TL120_Safari3"><a href="#fn:TL120_Safari3" rel="footnote">1</a></sup>。</p>
<h4>Safari の組み込み検索フィールドを拡張する</h4>
<p>AcidSearch のように Safari の検索ボックスを拡張するプラグインの代替としては以下のようなものがあります。</p>
<div class="exref">
<ul>
<li>Yahoo! に買収された <a href="http://www.inquisitorx.com/safari/index_jp.php" title="Inquisitor. Instant web search for Safari.">Inquisitor</a></li>
<li>検索ボックスの拡張に留まらない多機能プラグイン <a href="http://www.machangout.com/" title="Glims beta 11 for Safari | www.MacHangout.com">Glims</a></li>
</ul>
</div>
<p>Safari の Google 検索窓ではなく、<a href="http://mozilla.jp/support/firefox/tutorials/search" title="Mozilla Japan - Firefox サポート - 使い方ガイド - 様々な Web 検索機能">Firefox のスマートキーワード</a>のようなアドレスバーからの検索なら、以下のようなプラグインがあります。</p>
<div class="exref">
<ul>
<li>これまた Safari 使いには欠かせない多機能プラグイン <a href="http://hetima.com/safari/stand.html" title="SafariStand - hetima.com">SafariStand</a></li>
<li>単機能なら <a href="http://purefiction.net/keywurl/">Keyurl</a>（現在、サイトにつながりません…）</li>
</ul>
</div>
<h4>Google のサイト内検索を簡単にしたい</h4>
<p>前置きが長くなりましたが、上記に紹介したような AcidSearch 代替プラグインでは、どうしてもできないことがあります。サイト検索です<sup id="fnref:TL120_Site_Search"><a href="#fn:TL120_Site_Search" rel="footnote">2</a></sup>。私はサイト内検索をすることが多いので、これができないとどうしても効率に不満が残ります。AcidSearch はサイト内検索ができたので、よかったのです。</p>
<p>いろいろ調べてみたのですが、現在、Safari のプラグインでこのサイト検索ができるものはなさそうです。Firefox や IE なら <a href="http://toolbar.google.com/intl/ja/">Google ツールバー</a>を使う方法もあるのですが…。</p>
<h4>サイト内検索をするブックマークレット</h4>
<p>しかたないので、サイト内検索は Bookmarklet で実現することにしました。もう既に誰かが同様のものを作っていそうなきもしますが、以下で公開しておきます。</p>
<pre><code>javascript:l=location.hostname;k='%22'+encodeURIComponent(window.getSelection())+'%22';window.location='http://www.google.com/search?as_q='+k+'&amp;as_sitesearch='+l;
</code></pre>
<p>使い方は、下記のリンクをブックマークしておいて、必要なときに呼び出すだけです。選択した単語部分をそのとき開いているサイト内で Google のサイト検索を用いて検索結果を表示します。</p>
<ul>
<li><a href="javascript:l=location.hostname;k='%22'+encodeURIComponent(window.getSelection())+'%22';window.location='http://www.google.com/search?as_q='+k+'&as_sitesearch='+l;
" title="選択語で Google のサイト検索を行う Bookmarklet">サイト検索</a></li>
</ul>
<p>検索結果は同一ウインドウで開きますが、新規ウインドウで開きたい場合は、<code>window.location</code> の部分を <code>window.open</code> にすればいけると思います。</p>
<p>この Bookmarklet をブックマークバーの一番左に置いておけば、<kbd>&#8984;1</kbd> (cmd+1) で一発でサイト内検索を行うこともできます<sup id="fnref:TL120_Bookmark_Bar"><a href="#fn:TL120_Bookmark_Bar" rel="footnote">3</a></sup>。</p>
<h4>Safari の window.getSelection() の挙動</h4>
<p>このブックマークレットを作るにあたって、ちょっとハマったのが、Safari の <code>window.getSelection()</code> の動作でした。</p>
<p>Safari では <code>window.getSelection()</code> はオブジェクトとして返ってくるのですが、それを例えば <code>window.getSelection().toString()</code> としても、テキストが得られないようなのです。</p>
<div class="exref">
<ul>
<li><a href="http://groundwalker.com/blog/2007/04/safari_window_getselection.html" title="Safari: window.getSelection() が返すオブジェクト (groundwalker.com)">Safari: window.getSelection() が返すオブジェクト (groundwalker.com)</a></li>
</ul>
</div>
<blockquote cite="http://groundwalker.com/blog/2007/04/safari_window_getselection.html" title="Safari: window.getSelection() が返すオブジェクト (groundwalker.com)">
<p>
プロパティを調べると、toString:[function] が定義されていることもわかる（toStringしか定義されていないこともわかる）。しかし、s.toString()=undefined なのだ。alert(s) とすれば、選択された文字列が表示されるので、toString()は実装されているように思うのだが。。。
</p>
</blockquote>
<p>いろいろ調べてみたのですが、WebKit Bugzilla #4609<sup id="fnref:TL120_WebKit_Bugzilla_4609"><a href="#fn:TL120_WebKit_Bugzilla_4609" rel="footnote">4</a></sup> なんかを見てみると、<code>toString</code> は Firefox と同様に動くようになったと書いてあります。ただ、上記の記事が 2007年 4月、#4609 の Fix は 2006年 1月なので、直っていてよさそうなものなのですが、Safari 3 になるまで修正が入らなかったのかもしれません。</p>
<p>この問題があったときに、回避策として <code>window.getSelection()</code> をテキストにする方法は、検索するといくつかでてきました。</p>
<ul>
<li><code>str=window.getSelection()+'';</code></li>
<li><code>str=unescape(escape(window.getSelection()));</code></li>
</ul>
<p>前者は、空のストリングを付加して、<code>window.getSelection()</code> の返すオブジェクトをテキストに変えているようです。</p>
<p>後者も似たようなものですが、私が公開している <a href="http://homepage.mac.com/travellers/software/AppleScript/index.html#Safari">Title+URI+Text.scpt</a> で使っている方法です<sup id="fnref:TL120_Title_URI_Text"><a href="#fn:TL120_Title_URI_Text" rel="footnote">5</a></sup>。</p>
<p>そんなわけで、以下のようなコードを書いてみました。</p>
<pre><code>javascript:l=location.hostname;k=window.getSelection();k='%22'+k+'%22';window.location='http://www.google.com/search?as_q='+k+'&amp;as_sitesearch='+l;
</code></pre>
<p>これでうまく動くような感じだったのですが、落とし穴がありました。このコードだと、取得した文字列が元のページの文字コードに依存する形になり、文字列を Google に渡したときに元のページの文字コードに基づいて URI エンコードした形で URL に検索クエリが入ってしまうのです。UTF-8、Shift_JIS のページでは問題なく動いたのですが、EUC-JP のページではクエリが文字化けしてしまうことが判明しました。</p>
<p>どうしたものかなーと思ったのですが、ページから取得した文字列を <code>encodeURIComponent</code> したところ、UTF-8 で URI エンコードされた文字列になったので、めでたく動くようになりました。</p>
<p>というわけで、簡単かと思いきや、意外に手数をかけてしまいました。</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn:TL120_Safari3">
<p>当初はそれ以外にも Safari 3 非対応プラグインが多かったのでアップデートをためらっていたのですが、ほとんどが Safari 3 対応、もしくは別の代替手段が出てきたために、<a href="http://www.pozytron.com/archives/2007/11/acidsearch_07b3.html" title="pozytron: news: AcidSearch 0.7b3">AcidSearch</a> が私には最後の障害となっていました。&#160;<a href="#fnref:TL120_Safari3" rev="footnote">&#8617;</a></p>
</li>
<li id="fn:TL120_Site_Search">
<p><a href="http://www.google.com/intl/ja/help/features.html#sitesearch">サイト検索 - Google ヘルプ: 検索機能</a>&#160;<a href="#fnref:TL120_Site_Search" rev="footnote">&#8617;</a></p>
</li>
<li id="fn:TL120_Bookmark_Bar">
<p>Bookmarklet に限らず、Safari のブックマークバーに登録されているブックマークは左から順番に <kbd>&#8984;</kbd> (cmd) + 数字 のキーボードショートカットが割り振られています。&#160;<a href="#fnref:TL120_Bookmark_Bar" rev="footnote">&#8617;</a></p>
</li>
<li id="fn:TL120_WebKit_Bugzilla_4609">
<p><a href="https://bugs.webkit.org/show_bug.cgi?id=4609">Bug 4609 - window.getSelection().toString() is undefined (range object returned from window.getSelection() is useless)</a>&#160;<a href="#fnref:TL120_WebKit_Bugzilla_4609" rev="footnote">&#8617;</a></p>
</li>
<li id="fn:TL120_Title_URI_Text">
<p><code>window.getSelection()</code> で AppleScript から Safari の選択テキストが取得できなくなったために採用した方法なのですが、なんでこうする必要があるのかという背景は今回知りました。&#160;<a href="#fnref:TL120_Title_URI_Text" rev="footnote">&#8617;</a></p>
</li>
</ol>
</div>
]]>
</content:encoded>
</item>
</channel>
</rss>