jQueryではそれぞれのイベントに対応したメソッドを利用してイベントハンドラを設定します。JavaScriptのDOM0ではイベント属性をイベントハンドラとして利用しました。また、documentオブジェクトを指定してそのプロパティにイベントハンドラを設定することもありましたが、ブラウザ依存の問題がありました。さらにはaddEventListenerにおいてもIEの問題があります。そのような問題点を考えるとイベントの設定はjQueryが最も手軽で確実です。簡単なイベントの設置方法はjQueryでイベントを使ってみるを参考にしてください。
今回はイベントにかかわるバブリングに焦点を置きます。
jQueryのバブリング
JavaScriptのイベントには3つの段階(キャプチャリング、バブリング、ターゲット)の伝播がありました。
jQueryにはイベントのバブリングがあります。
子要素でイベントが起こるとそれが親要素でも発火します。それはさらに親要素へと続きます。
jQueryのイベントの伝播を試してみます。
サンプル
$(function(){ $("article").click(function(){ $('article').css('background-color','red'); }); });
<article> <section> <ul> <li>クリック</li> </ul> </section> </article>
$(“article”).clickとすることでarticleにイベントハンドラを設置しています。
article部分(白の背景色部分)をクリックするとarticleの背景色が赤になります。
ところが、articleの子要素section(ピンクの背景色部分)をクリックしてもarticleの背景色が赤になります。
また更にsectionの子要素li(青の背景色部分)をクリックしてもarticleの背景色が赤になります。
つまり子要素で起こったイベントはその親要素へ伝わり、親要素に仕掛けた発火点に着火する事になります。
この現象がバブリングというイベントの伝播になります。
liをクリックするとイベントのバブリングが起こり、sectionにもarticleにもクリックイベントが伝わります。
そしてarticleに設置したイベントハンドラが発火してarticleの背景色が赤になるわけです。
けれども今度はグレー部分のbody要素をクリックしても伝播はおこりません。これはキャプチャリングが起こってないことを示しています。
jQueryでバブリングを止める
jQueryでバブリングを止める方法はstopPropagationメソッドを使用します。
- web標準ではイベントオブジェクトのstopPropagationメソッド(DOM)を実行
- IEはイベントオブジェクトのcancelBubbleプロパティにtrueを代入
article部分をクリックしたら背景色が赤に変わる。けれども子要素のselectやliクリックしても色を変えたくない場合にはliやsectionのバブリングを止めないといけません。バブリングの止め方は以下のようになります。
$(function(){ $("article").click(function(){ $('article').css('background-color','red'); }); $("li,section").click(function(e){ if(e.stopPropagation){ e.stopPropagation(); }else{ e.cancelBubble = true; } }); });
function(e)のeはイベントオブジェクトです。e.stopPropagation()はイベントオブジェクトが持つメソッドです。function(e)のeは変数ですから適当に自分で名前をつけても良いのですが、一般的にイベントオブジェクトと解りやすいようにeventとしたり、evtとしたりあるいは簡単にeとしたりする場合が多いです。
return falseの問題
イベントで設定されたfunction内にreturn falseと記述すると、stopPropagationメソッドとpreventDefaultメソッドの両方の効果を発揮します。 return falseはイベントオブジェクトではありませんが、同様の働きをしてくれますので上手に使うのは有りです。けれども、バブリングの知識なくて、ただa要素のリンク機能を停止する目的で使用していたなら思わぬところで意図しない動きにつながる可能性があります。
イベントデリゲート
そもそも、何故バブリングが必要なのでしょうか。
例えばサンプル のような例を見てみましょう。
<ul> <li>クリックされていません。</li> <li>クリックされていません。</li> <li>クリックされていません。</li> <li>クリックされていません。</li> <li>クリックされていません。</li> </ul>
リスト要素をクリックするとそのテキストを変更するスクリプトのコードは次のようになります。
サンプル
$(function(){ $("li").click(function(){ $(this).text("クリックしました!"); }); });
この場合は全てのliに対してマウスクリックのイベントハンドラを設置したことになります。そしてthisを使用することでクリックされた特定のliを判別するものです。
バブリングの機能を使うともっと効率良くイベントハンドラを設置できます。
$(function(){ $("ul").click(function(e){ $(e.target).text("クリックしました!"); }); });
イベントハンドラをliの親要素であるulに設置します。そうするとイベントハンドラはul要素1つに設置されたことになります。あとはthisのかわりにe.targetを使用してイベントの発火点を特定するわけです。
このようなバブリングを活用したイベントの設定方法をイベントデリゲートといいます。