読者です 読者をやめる 読者になる 読者になる

anti scroll

ブラウザと小説の新しい関係を模索する

textNodeの出力オプションを追加

2chからのアクセスに、珍しくリファラが付いてたので、元スレを覗いてみたのですが、縦書き文庫に投稿された作品へのリンクに「踏まないほうがいいよね?」ってレスが付いていて、地味に傷ついたのでした。

capturePageTextオプション

それはさておき、表題の件です。

まだリリースはされていませんが、nehan.jsのリポジトリ上では、 Nehan.PageStreamsetContentや、 Nehan.PageStreamasyncGetという関数のオプションに、capturePageTextという新しいオプションが追加されました。

これを有効にすると、出力されるページに、DOMElementで言うところのtextNode的な文字列が入ってきます。

var pe = Nehan.createPagedElement().setContent("<p>foo</p>", {
  capturePageText:true, // textNodeを出力する
  onProgress:function(tree, ctx){
    console.log(tree.text); // "foo"
  }
});

この機能を使えば、例えばビューアーに検索機能を付けたい場合、filter関数を使って、

var search_pages = function(pe, keyword){
  return pe.filter(function(page){
    return page.text.indexOf(keyword) >= 0;
  });
};

var cool_pages = search_pages(pe, "cool!");

とかやれば、キーワードにマッチするページ配列が取得できるようになります。

Nehan.BoxとNehan.Pageの違い

ちょっとした捕捉ですが、filterが返すのは、Nehan.Pageの配列ではなく、Nehan.Boxの配列であることに注意して下さい。

つまり、上のプログラムにおけるcool_pagesのそれぞれには、elementメンバが存在しません。

console.log(typeof cool_pages[0]); // "Box"
console.log(typeof cool_pages[0].element); // "undefined"

これはなぜかというと、nehan.jsが計算するページは、実際にそのページが画面に表示されるまでは論理レイアウトNehan.Box)として保存されているからです。

nehan.jsでは、画面に表示されるときになって初めて、論理レイアウト(Nehan.Box)がon the flyで実レイアウト(Nehan.Page)に変換されます(これはたかだか1ページぶんの変換なので、一瞬で終わります。もちろん評価が済んだページはキャッシュされるので、再計算も発生しません)。こうやって生DOMの生成を遅延することで、全体のパーススピードを上げているわけです。

まだ表示されていないページを検索結果に含めるために、filter関数の戻り値はNehan.Boxの配列となっています。

余談

最後にnehan.jsの検索性について、ちょっと余談です。

よくnehan.jsのbrタグについて「CTRL+Fの検索が使えない」と言う人がいますが、段組みで表示する場合はその通りとして、ページ送りの組版にとってはどのみちCTRL+Fはあまり意味がないことに留意していただきたく。

例えば、検索ワードが最終ページにヒットするケースを考えて下さい。

そういう場合、いま見ているページをすっ飛ばして、いきなり最終ページにジャンプするわけにはいかないじゃないですか。

だから、ページ送りで表示するドキュメントの場合、どのみち検索機能は別のUIを用意する必要があるわけです。

だからbrはたいして問題じゃないように思うわけですが、どうなんでしょうね?