Event: Using Event Utility and Event Delegation to Improve Performance
YUIのEvent UtilityのExamle4はEvent Delegation。Event Delegationとかいう名前だと、一般的な用語かと思ってググッてみるが、Java関連で出てくるのみ。awt関連(自分はJavaEEの人だから、むかーしかじった程度)の記事に「イベント処理をListnerを仕込んで、イベント処理を委譲させるモデル」とか書いてあるので、これは、Javascriptでは普通にやってること。
YUIの説明を読むと、「親要素に1つのイベントハンドラーを仕込んで、子要素の繰り返しをListenさせる」と書いてある。子要素のイベントは、親に向かって昇ってくる(伝播してくる。原文ではBubble Upと書いてある)ので、効率的で信頼性が高い、イベントリスナーがResource Consumingだからimprove performanceという意味なのだろう。
この例でも、Loggerにログを書き出しているので、alertに変更してサンプリング。
<HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=UTF-8"> <META http-equiv="Content-Style-Type" content="text/css"> <TITLE>Ajax_Sampling</TITLE> <style type="text/css"> <style> </style> <!-- 読み込むscriptはyahoo-dom-event/yahoo-dom-event.jsだけ。 --> <script type="text/javascript" src="scripts/yui/yahoo/yahoo-min.js" ></script> <script type="text/javascript" src="scripts/yui/event/event-min.js" ></script> <script> function clickHandler(e) { //get the resolved (non-text node) target: //イベントからターゲットオブジェクトを取得 var elTarget = YAHOO.util.Event.getTarget(e); //walk up the DOM tree looking for an <li> //in the target's ancestry; desist when you //reach the container div while (elTarget.id != "container") { //are you an li? if(elTarget.nodeName.toUpperCase() == "LI") { //yes, an li: so write out a message to the log //イベント発生のターゲットが<li>ならalertをあげるように変更。 alert("The clicked li had an id of " + elTarget.id); //YAHOO.log("The clicked li had an id of " + elTarget.id, // "info", "clickExample"); //and then stop looking: break; } else { //イベントが親に向かって伝播するから、これでよい?? //wasn't the container, but wasn't an li; so //let's step up the DOM and keep looking: elTarget = elTarget.parentNode; } } } //attach clickHandler as a listener for any click on //the container div: //<li>の親要素の<div>にハンドラーを仕込む。 YAHOO.util.Event.on("container", "click", clickHandler); function mouseHandler(e) { var elTarget = YAHOO.util.Event.getTarget(e); while (elTarget.id != "container") { if(elTarget.nodeName.toUpperCase() == "LI") { alert("The li that was mousedover had an id of " + elTarget.id); // YAHOO.log("The li that was mousedover had an id of " + // elTarget.id, "info", "mouseExample"); break; } else { elTarget = elTarget.parentNode; } } } //クリックと同じなので、使わない。 //YAHOO.util.Event.on("container", "mouseover", mouseHandler); </script> </HEAD> <BODY> <div id="container"> <ul id="list"> <li id="li-1">List Item 1</li> <li id="li-2">List Item 2</li> <li id="li-3">List Item 3</li> <li id="li-4">List Item 4</li> <li id="li-5">List Item 5</li> <li id="li-6">List Item 6</li> </ul> </div> </body> </HTML>
これでOK。下のようにでます。(注;mouseoverイベントを使うと、リストの横を通るたびにalertがあがってしまいます。そのときには、リストの先頭より前を通れば、リスナに引っかかりません)