Kanasan.JS Prototype.js CodeReading #6 に行ってきました (当日のチャットログ、参加者のブログ記事一覧)。今回は Prototype.js 1.6.0.2 の 3375 行目、フォームに関する部分から最後まで読みきりました。
フォームコントロールを取得するメソッドですが、tabindex 属性でタブ移動順が指定されていた場合は、その順序がもっとも早いコントロールを返そうとしているようです。しかしその際、tabindex 属性の値が 0 のものを値が 1 のものより優先しているようで、実際のタブ移動順と得られる結果が一致しません。HTML 4 では tabindex 属性の値 0 は、tabindex 属性を指定しないのと同じ効果を持つはずなのですが。
多くのブラウザでは、フォームコントロールのフォーカスと選択範囲は別個に管理されています。ですので、フォーカスのないコントロールの選択範囲を変更することも可能です。もっとも、フォーカスがなければ選択範囲を変更してもそれを視認できないかもしれませんが。
シリアライザという名前からフォームコントロールの値を取得する関数群かと思いきや、その名に反してゲッタとしての役割も負っています。各関数は引数 element と value をとり、value が省略されていればゲッタ、指定されていればセッタとして振舞うようです。
select 要素には type プロパティがあり、その値は multiple 属性が指定されていれば "select-multiple"、指定されていなければ "select-one" となります。Prototype.js ではこのプロパティを見て、ゲッタの処理を selectOne メソッドと selectMany メソッドに振り分けています。
通常、ある要素に登録されているイベントリスナを取得することはできません。Prototype.js では addEventListener メソッドなどでリスナを要素に登録する際、cache オブジェクトにもそのリスナを格納しておくことで、要素からリスナを取得できるようにしています。cache オブジェクトの構造は次のようになっています。
Event.cache = {
"ある要素のイベント ID": {
"click": [
click イベントに登録されたあるリスナのラッパ関数,
click イベントに登録された別のリスナのラッパ関数,
...
],
"イベント名": [
そのイベントに登録されたリスナのラッパ関数,
...
],
...
},
"別の要素のイベント ID": { ... },
...
};
ここで、要素のイベント ID とは Prototype.js が要素ごとに生成する ID です。また、ユーザーから渡されたリスナをそのまま登録するのではなく、イベントオブジェクトの動作を拡張するラッパ関数を作成して (3866 行目、Event.createWrapper)、そのラッパ関数を登録しています。
pointer メソッドはマウスポインタの位置を取得するメソッドで、IE 以外では pageX / pageY プロパティの値をそのまま使っています。IEでは文書の表示モードが標準モードでも互換モードでもうまくいくよう、document.documentElement と document.body のプロパティを併用しています。stop メソッドはイベントの伝播をとめるとともに、そのイベントのデフォルトアクションをキャンセルします。
イベントの伝播やデフォルトアクション、文書の座標系については WEB+DB PRESS Vol. 46
セコメントをする