HTMLWalker

HTMLWalkerとは

最終更新
2005-03-29T00:43:58+09:00

HTMLWalkerは、簡単シンプルなJavaScriptのコンストラクタ関数で、JavaScriptによるDOMスクリプティングを補助します。インスタンスのwalkメソッドは、指定したノードから出発して文書順にノードを辿り、その都度nodeNameアトリビュートに基づいてハンドラを呼び出します。

雰囲気としてはDOM Level 2のNodeIteratorインターフェイスに似ていますが、それより低機能かつシンプルなもので、DOM Level 1 HTMLの実装だけを要求します:

何のメリットがあるのか

最終更新
2005-03-29T00:43:58+09:00

メリットはありません。ただ、場合によってはコードが読みやすくなります。また、人によってはメンテナンスがしやすくなるかもしれません。定義するハンドラによっては、稀に、getElementsByTagNameメソッドを多用する通常のDOMスクリプティングよりも実行が高速になります。

洒落で書いたのですが、いつの間にか手放せなくなっていることに気づいて公開しようと考えました。

使用方法

最終更新
2005-03-29T00:43:58+09:00
  1. 独自のハンドラ(コンストラクタ関数)を書きます。
  2. HTMLWalker.normalizeHandlerメソッドで、ハンドラを正規化します。
  3. HTMLWalkerのインスタンスを生成します。この時、ハンドラとトラバースを開始するノードをコンストラクタに引数として与えます。
  4. walkメソッドでトラバースを開始します。

試しに一対のDT, DD要素を含んだDL要素をトラバースしてみます。こんなHTML断片:

<dl id="TEST_DL"><dt>被定義語句</dt><dd>定義だらだら</dd></dl>

で、「被定義語句:定義だらだら」のような文字列を得ましょう。まずハンドラを書きます。

function DLHandler(){
  this.result = [];
  this["DT"] = function(dt){
  };
  this["DD"] = function(dd){
    this.result.push(":");
  };
  this["#text"] = function(node){
    this.result.push(node.data);
  };
}

配列を用意しまして、テキストノードを検知したらそのdataを配列に追加し、DD要素を検知したら「:」を追加しようってわけです。というわけでつまり、HTMLWalkerインスタンスがDD要素に到達すると、DLHandlerインスタンスをdhとすれば、そのDD要素を引数として渡された関数dh["DD"]が呼び出されるというわけです。dh["DD"]が未定義だった場合、dh["*"]が呼び出されます。でもこれも定義されていませんから、このままでは未定義値をcallしてしまいTypeErrorです。そこで、そのような関数を定義済みのハンドラ、HTMLWalker.DefaultHandlerに、プロトタイプチェインしてしまいます。その為のクラスメソッドを用意してあります。

HTMLWalker.normalizeHandler(DLHandler);

これでOKです。

またはJavaScript1.5なエンジンを利用するのであれば:

DLHandler.prototype.__proto__ = HTMLWalker.DefaultHandler.prototype;

こうした方が断然スマートってもんです。

ハンドラを書いたところで、HTMLWalkerを作成し、walkメソッドでトラバースを開始します。

var handler = new DLHandler;
var walker = new HTMLWalker(handler, document.getElementById("TEST_DL"));
walker.walk();

これで、目的の文字列は参照可能になっています。

典型的な使用例:カレンダー生成

最終更新
2005-03-29T00:43:58+09:00

都合の良い例を挙げてしまえば、HTMLを含め、どれだけコードが見通しの良いものになるかお見せしましょう。詳細はまた今度。