JavaScriptのイベント処理のtips
prototype.js前提ですが、JavaScriptでルートウィンドウ(*)のクリックイベントを拾う場合、次のように書きます。
document.observe('click', function() { 処理 });
(*) ブラウザで「ルートウィンドウ」という呼び名が適切とは思えませんが、まあ雰囲気は通じると思うので。DOMの用語を使うなら「文書ノード」と呼ぶべきかもしれません。
DOMのイベントは、イベントが発生したノードから文書ノード(ルートノード)に向かってイベントが伝播します(いわゆるバブリング)。正確には逆方向のキャプチャリングが先にありますが、v1.6以降のprototype.jsのobserveメソッドはaddEventListenerメソッド(https://developer.mozilla.org/en/DOM/element.addEventListener)の第3引数にfalseを渡しているのでキャプチャリングは無視できます。
特定のノードでクリックイベントを拾ってイベントリスナを書く場合、何も考慮せずに書くと、イベントの伝播が進んで、最後に文書ノードのイベントリスナが実行されてしまいます。多くの場合、特定ノードでクリックイベントを処理した場合、文書ノードのイベントリスナの処理は余計です。この場合、次のようにEvent.stopで伝播を止めるのが定石です。
a_node.observe('click', function(evt) { 処理...; Event.stop(evt); })
しかし、aタグのリンクをクリックする場合、イベント伝播を明示的に止められないので、文書ノードのイベントリスナが走ってしまいます。
こういう場合の対処を浜辺さんに聞いたところ、次のようなコードを教えてもらいました。
document.observe('click', function(evt) { if (/a/i.test(Event.element(evt).tagName)) return; 処理 });
これはトリッキーすぎると文句を言いましたが、別に普通、との答えでした。
JavaScriptは言語としてはそんなに嫌いではないのですが、こういうHTML絡みの微妙さが好きになれません。
- Category(s)
- カテゴリなし
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/inoue/js-event/tbping
Re:JavaScriptのイベント処理のtips
/a/i は /^a$/i にしないとspanとかにもマッチしちゃいますね。
そして、<a> <b> hoge </b> </a>こんなマークアップだとtargetがb要素になるのでDocumentのイベントが走ってしまいますね。。
これは上手い解決策も思いつきません(ベタにtargetのparentNodeをDocumentまで調べるしかないかも)。。
うーん、Documentのイベント周りは確かに微妙ですね。。
Re:JavaScriptのイベント処理のtips