iOSのWebViewに拡張メニューを追加するWebViewExMenu
2016/03/24
価値ある情報をユーザー視点で発信するブログ
2016/03/24
MobileSafariとWebView全般に拡張メニューを追加するWebViewExMenuというTweakを作ってみました。
MobileSafariの拡張じゃありません。Webブラウザの拡張でもありません。WebView全般で有効。
WebViewというのは、iPhoneのアプリケーションの中全般で部品として使われています。
Evernoteの中でも、Twitterクライアントの中でも、RSSリーダーの中でも、2ちゃんねるリーダーの中でも、サードパーティ製のWebブラウザでも有効です。
例えば、どこからでもはてなブックマーク登録Bookmarkletを呼び出したり、といったことができます。(自分はTwitterクライアント内のブラウザからはてブするために作りました)
もくじ
どこでもはてブできます。
実際の動作の様子です。
MobileSafariのみならず、RSSリーダーからも呼び出せています。
場所を選ばずメニューの表示ができ、機能の実行ができていることが分かるかと思います。
WebViewExMenuは、MobileSafari、WebView上でトリプルタップをすると表示されます。
ただ、ページ中がタップ可能なもので占められている場合など、タップを避けつつメニューを表示することが困難なケースはあるかと思います。
汎用性の実現、片手操作が可能であること、実装の簡単さからトリプルタップを選択しました。(続きは[MORE]から)
機能は三つあります。
MobileSafariのブックマークのルートにあるBookmarkletsフォルダ(Bookmarkletの複数形でBookmarklets)にあるブックマークレットを一覧から選んで実行できます。
Bookmarkletsフォルダの下層は再帰走査しません。ベタで置いてください。
SafariのブックマークからBookmarkletを実行する場合との違いは、実行結果に何らかの文字列が含まれていたら、それをクリップボードに転送することです。
例えば、以下のBookmarkletを実行すると、表示中のページのタイトルとURLがクリップボードに転送されます。
javascript:document.title + ‘ ‘ + window.location
XPathで掘れば、大概のスクレイピングはできるかと思います。
ページから欲しい情報を抜いてきて、サクっとクリップボードにコピー、ということができるわけです。
副次的なメリットとして、ブックマークレット実行までに、テキスト選択が解除されてしまうことがないというものがあります。
よって、選択テキストを取得して処理するタイプのBookmarkletを素直に動かすことができます。
Safariから選択テキストを扱うBookmarkletを実行する場合、ブックマークボタンを押した時点でテキストの選択が解除されてしまうため、少々面倒なBookmarkletの作りと手順が必要なのです。
iPhoneのwindow.getSelection()について – YutaKikuchiのTechBlog |
以下の例では、選択中のテキストをダブルクォートで括ったものがBookmarkletの返り値となり、クリップボードにコピーされます。
javascript:'”‘+document.getSelection()+'”‘
冒頭の「javascript:」は必要ありませんが、Safariのブックマークから起動する場合のことを考えて、付けておくのがいいでしょう。
逆に、クリップボードにコピーされたくない場合は、Bookmarkletの最後を文字列を返さないメソッドで終わるか、void(0)かなんかを実行してください。
Twitterクライアントなどの所有するURL Schemeから始まるURLをwindow.locationにセットして、別のアプリケーションを呼び出すBookmarkletは、iPhoneでは多用されます。
しかし、こうしたタイプのJavaScriptは、必ずしも期待通りの結果をもたらすとは限りません。JavaScriptを動かしたアプリケーション内のWebViewのdelegateメソッドの実装次第です。
UIWebViewの内部リンクからSafariを開いてみよう! – u_ |
例えば、Tweetlogixの中のWebViewでURL Scheme経由で別アプリケーションを呼び出そうとしても無反応。
一方で、Tweetingsだと呼び出せるといったような感じです。
JavaScript / Bookmarkletを実行しても、ウンともスンとも言わない。
そんなときはどうしましょう?
「設定>Safari>デベロッパ>デバッグコンソール」をオンにしましょう。エラーが出ていれば、それをデバッグコンソールで教えてくれるようになります。
デバッグコンソールは、Safariのアドレスバーの下に表示されます。
MobileSafari、WebViewでちょっと昔めのページを訪れると、ときどき化けて見られないことがあります。
ページの実際のエンコーディングと、ページ内で指定されているcharsetに不一致があったり、正しくない書き方だったりするのでしょう。
こんなとき、MobileSafari / WebViewだと処置のしようがありません。処置のしようがないんです。
さて、そんなWebページの文字化けの対策になるのがテキストエンコーディング選択機能です。
上記の六つのテキストエンコーディングから任意に選んで適用することができます。
そのどれかを選択すれば日本語の文字化けは回避することができるかと思います。
選択できるテキストエンコーディングは無数にあり、それを選択できるようにすることは可能ですが、無数の中から残したいものを選ぶUIを作る必要があるので、とりあえずはこのようにしてみました。
WebViewExMenuの項目「ソースを表示」を選択すると、表示中のページのhtmlのソースを見ることができます。
シンタックスハイライティングされ、行番号まであって見やすい表示です。
ソース表示モード中にWebViewExMenuを起動すると、「ソースを表示」から「ソース表示を解除」とボタン名が変わっています。
「ソース表示を解除」ボタンを押すと、通常のモードに戻ります。
WebViewExMenuをインストールすると、「設定>WebViewExMenu」が現れます。
※「PlainText.app First」の設定項目はVer.0.4から削除されています。
WebViewの初期化時にBookmarkletを読み込んでいます。
初期化とは、例えばMobileSafariなら、新しくウインドウを作ることが初期化です。
ここでWebViewExMenuのJavaScript実行メニューの内容が読み込まれます。
初期化時に読み込んだBookmarkletは、そのWebViewが保持します。
MobileSafariのBookmarkletsフォルダに手を加え、さらにMobileSafariで新しくウインドウを作った場合、古いウインドウと新しいウインドウのJavaScript実行メニューの内容は違ったものになります。
MobileSafariにBookmarkletsフォルダを作ったのが、WebViewExMenuを実行しようとしているWebViewが生成されたのより後である場合、まだそれらが無かったときにそのWebViewは生成されているため、MobileSafariにBookmarkletsフォルダの中身は表示されません。
MobileSafariなら、新しくウインドウを作ってからWebViewExMenuを実行してください。
この辺は感覚的でないのは分かりますが、都度読み込もうとすると不具合が出るため、このような仕様になっています。
Bookmarkletを編集してもすぐには反映されません。
WebViewの初期化時にBookmarkletを読み込んでいるので、一度WebViewを閉じないと更新は反映されません。都度読み込もうとすると不具合が起きるための仕様です。
片手でできる範囲の起動方法ではベストだと思っているので、考えを曲げる気はありません。
Activator、SBSettingsの場合は1対多の通信となり、「どのWebViewで実行するか」を絞る手順が必要になります。
それを解決する手段はありませんし、そんなことをしたい人もまた居ないはずです。1画面に複数のWebViewが存在する、ということもあります。
ActionMenuならいけますが、メニューの奥まったところから実行するのは得策ではないと思います。コピー/ペーストに並べて置くようなものでもありません。
よって、対応するつもりはありません。
New野良リポジトリに置いておきました。
「WebViewExMenu」で検索してください。
無保証です。
WebViewExMenuのJavaScript実行機能は、fladdictさんの「SpellBook」
fladdict » SpellBook 右クリックからブックマークレットを起動できる拡張 |
paella (@hkato193)さんの「LibraMagico」
[Mac][SIMBL][Bookmarklet] SafariでもSpellBookの感動が得られるプラグイン「LibraMagico」を書いてみた – Ni chicha, ni limona -平均から抜けられない僕- |
にインスパイアされて作りました。アイデアは随分前から考えていたんですけどね。