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があがってしまいます。そのときには、リストの先頭より前を通れば、リスナに引っかかりません)