2010年10月31日日曜日

EPUB 内リンクと外部リンクで動作を変える

 Mac 用 EPUB プレヴュワ開発について。

 EPUB の実体は (X)HTML やけん、本文中に <a href="http://www.google.com/">Google</a> みたいなハイパリンクを入れることができる。

 EPUB プレヴュワの表示エンジンには WebKit を使っとるけん、何もしなくてもリンククリックでページ遷移をすることはできる(ただし、target="_blank" 等で新しいウィンドウを開くタイプのリンクの場合はちょっとしたコードを書く必要がある)。ほなけど、作っとんのはあくまでも EPUB を(簡易的に)閲覧するアプリケーションやけん、外部リンクの場合は Safari 等システムで指定されとるウェブブラウザで開いて、目次から各章へのリンクなどの同一 EPUB 内へのリンクはアプリケーション内のページ遷移で処理する必要がある。
 したがって、クリックしたリンクのリンク先 URL をページ遷移処理前に調べて、それが内部リンクなのか外部リンクなのかで動作を変える処理を入れる。

 ページ読み込み処理の前には webView:decidePolicyForNavigationAction:request:frame:decisionListener:
という WebPolicyDelegate 非形式プロトコルのメソッドが呼ばれる。これをオーヴァライドすることで上述の処理を実現できる。具体的には以下のような感じ。
- (void)webView:(WebView *)webView
decidePolicyForNavigationAction:(NSDictionary *)actionInformation
        request:(NSURLRequest *)request
          frame:(WebFrame *)frame
decisionListener:(id <WebPolicyDecisionListener>)listener
{
  int navigationType = [[actionInformation objectForKey:WebActionNavigationTypeKey] integerValue];
  if(navigationType == WebNavigationTypeLinkClicked) {
    NSDictionary *element = [actionInformation objectForKey:WebActionElementKey];
    NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
    if(![[linkURL scheme] isEqualToString:@"file"]) {
      [[NSWorkspace sharedWorkspace] openURL:linkURL];
      [listener ignore];
    }
  }

  [listener use];
}
 actionInformation には読み込み処理がトリガされたアクションに関するデータが NSDictionary で入っている。その WebActionNavigationTypeKey キィには、リンククリックやフォームのサブミット等、どのような操作によって読み込み処理が発生したのかが入っている。WebActionElementKey キィには要素の詳細なデータがやはり NSDictionary で入っとるけん、そこからリンク先の URL を調べることができる。内部リンクであれば、リンク先の URL のスキームは file になっとるはずやけん、file 以外ならばシステム指定のブラウザで開く処理とディフォルトの動作を無視させる [listener ignore]; の処理を入れる。

 上記のようなコードを書いたあとは、Interface Builder において WebView の Policy Delegate を接続してやると、内部リンクと外部リンクで動作を変えた処理をできるようになる。

0 comments:

コメントを投稿