Yahoo! UI Library:: Event

http://developer.yahoo.net/yui/event/index.html

Yahoo! UI Library:: Event

The Event Utility facilitates the creation of event-driven applications in the browser by giving you a simplified interface for subscribing to DOM events and for examining properties of the browser's Event object. The Event Utility package includes the Custom Event Object; custom events allow you to "publish" the interesting moments or "events" in your own code so that other components on the page can "subscribe" to those events and respond to them. The Event Utility package provides the following features:

  • Flexible method of attaching event handlers to one or more elements
  • Automatically defers attaching handlers to elements that are not yet available
  • Automatic scope correction
  • Automatic event object browser abstraction
  • Ability to include an arbitrary object to be sent to the handler with the event
  • Utility methods to access event properties that require browser abstraction
  • Automatic listener cleanup
  • A mechanism for creating and subscribing to custom events


Eventユーティリティを使うと、ブラウザイベントオブジェクトのプロパティを調べるインターフェースと、DOMイベントを待ち受けるシンプルなインターフェースで、ブラウザ上でイベント主導のアプリケーションを創り出せます。Eventユーティリティのパッケージにはカスタム・イベント・オブジェクトが含まれています。カスタムイベントを使うと、自分のコードの中でおもしろい瞬間?や"events"を"publish"できます。ページに組み込んだ他のコンポーネントがカスタムイベントに対応し、反応するようになります。イベントユーティリティは以下のような特徴を持っています

・一個、もしくはたくさんの要素にイベントハンドラをくっつける柔軟性の高いメソッド
・要素を取得出来ない状態でも、ハンドラを要素にくっつける作業を自動的に遅延させてくれる(要素を取得するときまで遅らせる)
・スコープの自動訂正
・イベントオブジェクトとブラウザ(window.event.)の分離
・どんなオブジェクトでもイベントハンドラに送ってインクルードする
・ブラウザの分離?が必要なイベントプロパティにアクセスできるメソッドをもつ
・リスナーの自動撤去
・カスタムイベントを作り出し待ちうけるメカニズム

Getting Started

<!-- Namespace source file -->

<!-- Event source file -->
 

Eventコンポーネント YAHOO.util.Event. で定義されます

Basic Events

To attach an event handler to the DOM, use this code:

var oElement = document.getElementById("elementid");
function fnCallback(e) { alert("click"); }
YAHOO.util.Event.addListener(oElement, "click", fnCallback);

These lines of code:

Declare a variable oElement and assign a specific element in the DOM to that variable.
Define a callback function, fnCallback(e), to handle the specified event.
Call the addListener method on the Event object to bind an event to the DOM element. The addListener method takes three arguments: the element the event is bound to (oElement), the event to bind (click), and the function callback (fnCallback).

To attach an event handler by element ID, use this code:

function fnCallback(e) { alert("click"); }
YAHOO.util.Event.addListener("elementid", "click", fnCallback);
This example is the same as the first except here the elementid is the id attribute of the targeted DOM element (a string value). The Event component attempts to find the DOM element by this id value.

To attach an event handler to multiple elements, use this code:

var ids = ["el1", "el2", "el3"]; // array can contain object references, element ids, or both
function fnCallback(e) { alert(this.id); }
YAHOO.util.Event.addListener(ids, "click", fnCallback);
These lines:

Declare an array of ids for the element IDS. The array can contain string IDs or object references.
Define a callback function, fnCallback(e), to handle the specified event.
Call the addListener method on the Event object to bind an event to the DOM element. In this case the first argument to the addListener method is the ids array rather than a single element or ID.
See the examples below in Using Event and Using CustomEvent or the API Documentation for more details.


イベントの基本


イベントハンドラをDOMと結びつける場合、こんなコードを書きます

var oElement = document.getElementById("elementid");
function fnCallback(e) { alert("click"); }
YAHOO.util.Event.addListener(oElement, "click", fnCallback);

一行ずつ見ていきます

oElement変数を宣言し、DOMの中から要素を指定して変数に代入します。
イベント・オブジェクトに対してaddListener()メソッドを呼び出し、イベントとDOM要素を結び付けます。addListener()メソッドは引数を3つとります
①イベントと結びつく要素 -> oElememnt
②イベント ->click
③コールバック関数 ->fnCallback


要素IDを使って、イベントハンドラをセットするには こんな書き方をします

function fnCallback(e) { alert("click"); }
YAHOO.util.Event.addListener("elementid", "click", fnCallback);

引数"elemetid"がDOM要素のID属性の文字列であるいがいは、一個目のサンプルと同じです。EventコンポーネントはID値を使ってDOM要素にアクセスしようとします。


一個のイベントハンドラを複数の要素にセットするには、以下のように書きます

var ids = ["el1", "el2", "el3"]; // オブジェクトのリファレンス、要素のIDのどちらかを配列に入れる
function fnCallback(e) { alert(this.id); }
YAHOO.util.Event.addListener(ids, "click", fnCallback);

①要素IDのids配列を宣言します。配列には、IDの文字列かオブジェクトのリファレンスを入れます。
②コールバック関数 fnCallback(e)定義します。イベントを指定してハンドリングできます。
③addListener()メソッドを呼び出し、イベント・オブジェクトをDOM要素に結び付けます。
④今回は、addListener()メソッドのへ一個目の引数が要素一個、IDではなくids配列になっています。
EventやCustomEventを使うにあたってサンプルを見るか、詳細はAPIドキュメントに目を通してください


補足:
*ID "el1" , "el2" , "el3" を"click"するとコールバック関数が呼び出されます。コールバック関数の引数(e)は、addListener()メソッドによって呼び出された要素の参照を含んだ「イベントオブジェクト」です

このライブラリを使えば、HTMLタグの中にハンドラ()を記述する必要がなくなり、JavascriptのコードとHTMLのコードを分離することができます。IDだけでアクセスできるのが簡単でいいですね。

Using Event

This section describes several common features and uses of the Event component.

  • Handler Attachment Deferral
  • Automatic Scope Correction
  • Automatic Event Object Browser Abstraction
  • Send an Arbitrary Object to the Event Handler


イベントしる


このセクションでは、イベントコンポーネントの使い方、特徴について載せています

  1. ハンドラとりつけの延長
  2. 自動のスコープ訂正
  3. イベントオブジェクトとブラウザ(window.event.)の分離
  4. イベントハンドラにはどんなオブジェクトでも渡せる

1.Handler Attachment Deferral

If you attempt to attach a handler to an element before the page is fully loaded, the Event component will attempt to locate the element. If the element is not available, Event periodically checks for the element until the window.onload event is triggered. Handler deferral only works when attaching handlers by element id; if you attempt to attach to a DOM object reference that is not yet available, the component has no way of knowing what object you are trying to access.


1.ハンドラとりつけの延長


ページ読み込みが完了する前に要素にハンドラをセットしようとすると、Eventコンポーネントは要素の場所を探そうとします。もし要素がまだ定義されていない場合、Eventは定期的に要素があるかどうかを window.onloadイベント中にチェックします。ハンドラセットの延長は要素IDを使ってハンドラセットをやろうとしているときだけに機能します。まだ宣言されていないDOMオブジェクトのリファレンスを使おうとした場合、コンポーネントには あなたがアクセスしたいオブジェクトを知るすべをもちません。

補足:
<body>より前にJavascritpを記述して、getElementById()メソッドを使おうとすると 指定したHTML要素が定義される前にJavascriptが実行されてしまうので、未定義エラーがでます。このエラーのトラップ機能として使えるみたいです。

2.Automatic Scope Correction

Event handlers added with the attachEvent or addEventListener methods are executed in the window scope, so using "this" in your callback references the window object. This is not very useful. By default, the Event component automatically adjusts the execution scope so that "this" refers to the DOM element that the event was attached to. However, the event subscriber can override the scope so that "this" refers to the custom object that is passed into the addListener call.


2.スコープの自動訂正


attachEvent()メソッド、addEventListener()メソッドで組み込んだEventハンドラは"window"オブジェクトのスコープで実行されます。"this"を使うと、コールバック関数はwindowオブジェクトを参照してしまいます。これ、いくない。デフォルト設定で、Eventコンポーネントは実行スコープを自動的に調整してくれます。これによって、"this"の参照先はイベントがセットされたDOM要素になります。(つまりイベントを呼び出した要素自身)
しかし、イベントの待ちうけ元?はスコープをオーバーライドできます。これによって、"this"の参照先がカスタムオブジェクトになります。カスタムオブジェクトは、addListener()の呼び出しへ渡されます。


*attachEvent() IE
*addEventListener() firefox , operaなど
要素に「リスナー」をセットするメソッドです。ここら辺の「DOMイベントハンドリングモデル」についての詳しいことは羽田野さんの書いたAJAX Webアプリケーション アイデアブックを見るとすっごい分かりやすく書いています。

3.Automatic Event Object Browser Abstraction

The first parameter your callback receives when the event fires is always the actual event object. There is no need to look at window.event.


3.イベントオブジェクトとブラウザ(window.event.)の分離


イベントが起こったときにコールバックがもらうパラメータの一個目は、常にイベントオブジェクトです。window.event.を見る必要はありません。

4.Send an Arbitrary Object to the Event Handler

It is common in OO JavaScript development to have a custom object listen for an event, access internal properties and execute internal methods in response. Since the event handler is executed in the scope of the element, the custom object properties are not available through the "this" property as one might expect. You can work around this in a number of ways: by creating closures, or creating circular references between your custom object and the element. The Event component enables you to pass your custom objects directly to the event handler so you do not have to use any of these (potentially leaky) methods to gain access to that custom object. Pass your custom object as the fourth parameter to the addListener method, and that object is passed in as the second parameter to your callback function:

function MyObj(elementId, customProp, callback) {
   this.elementId = elementId;
   this.customProp = customProp;
   this.callback = callback;
}

MyObj.prototype.addClickHandler = function() {
   YAHOO.util.Event.addListener(this.elementId, "click", this.callback, this);
};

function fnCallback1(e, obj) {
  // the execution context is the html element ("myelementid")
  alert(this.id + " click event: " + obj.customProp);
}

function fnCallback2(e, obj) {
  // the execution context is the custom object
  alert("click event: " + this.customProp);
}

var myobj = new MyObj("myelementid", "hello world", fnCallback1);

// One way to add the handler:
myobj.addClickHandler();

// This will do the same thing:
YAHOO.util.Event.addListener("myelementid", "click", fnCallback1, myobj);

// If we pass true as the final parameter, the custom object that is passed
// is used for the execution scope (so it becomes "this" in the callback).
YAHOO.util.Event.addListener("myelementid", "click", fnCallback2, myobj, true);

4.イベントハンドラにはどんなオブジェクトでも渡せます


オブジェクト指向Javascriptの開発では、イベントをとらえるカスタム・オブジェクトを使うは普通のことです。カスタム・オブジェクトは内部プロパティにアクセスし、レスポンス時に内部メソッドを実行します。
イベントハンドラは要素自身のスコープで実行されるので、カスタム・オブジェクトのプロパティは、"this"プロパティを使って取得できません。他にもいろんなやり方があります。例えば、クロージャの作成や、カスタム・オブジェクトと要素の間に相互参照をもうけること(互いにリファレンスする?)です。
Eventコンポーネントを使うと、イベントハンドラに直接カスタムオブジェクトを渡せますので、さきほどのような方法を使う必要がなくなります(漏れがあるかもしれませんが)
addListener()メソッドに4つ目のパラメータとしてカスタム・オブジェクトを渡します。するとカスタムオブジェクトはコールバック関数に2つ目パラメータとして渡されることになります。

//カスタム・オブジェクトのコンストラクタ
function MyObj(elementId, customProp, callback) {
   this.elementId = elementId;
   this.customProp = customProp;
   this.callback = callback;
}
//カスタム・オブジェクトのプロトタイプメソッド(インスタンスメソッド)の定義
//四つ目の引数のthisはMyObjである
MyObj.prototype.addClickHandler = function() {
   YAHOO.util.Event.addListener(this.elementId, "click", this.callback, this);
};

//コールバック関数の定義
function fnCallback1(e, obj) {
  // 実行コンテキストはHTML要素の ("myelementid")
  alert(this.id + " click event: " + obj.customProp);
}

function fnCallback2(e, obj) {
  // 実行コンテキストは、カスタム・オブジェクトになる
  alert("click event: " + this.customProp);
}

//カスタムオブジェクトのインスタンスの作成

var myobj = new MyObj("myelementid", "hello world", fnCallback1);

// イベント追加の方法その①
myobj.addClickHandler();

// 上と同じ意味
YAHOO.util.Event.addListener("myelementid", "click", fnCallback1, myobj);

//
// 最後の引数に"final"を渡すと、関数に渡されるカスタムオブジェクトが
// 実行スコープで使われる(つまり"this"がコールバックになる)
YAHOO.util.Event.addListener("myelementid", "click", fnCallback2, myobj, true);

Using CustomEvent

This section describes several common uses of the CustomEvent component, with examples. CustomEvent component enables you to define and use events not available by default in the DOM.

  1. Defining a Custom Event
  2. Subscribing (Listening) to a Custom Event
  3. Creating a Callback
  4. Triggering the Event


カスタムイベントの使用


このセクションにはCutomEventコンポーネントの使い方とサンプルを載せています。CustomEventコンポーネントを使えば、DOMのデフォルトにはないイベントを定義し使うことができるようになります。

  1. Custom Eventの定義
  2. カスタムイベントの待ち受け(リスニング)
  3. コールバックをつくる
  4. イベントのトリガのやり方

1.Defining a Custom Event

To define a custom event type, create a new instance of CustomEvent:

// custom object
function TestObj(name) {
    this.name = name;
    // define a custom event
    this.event1 = new YAHOO.util.CustomEvent("event1", this);
}

The CustomEvent constructor creates a new custom event and takes two parameters. The first parameter is the type of event. This string is returned to listeners that receive this event so that they know what event occurred . The second parameter is the scope the listeners should fire from. The scope is "window" by default, but if you create custom events for your custom objects, you usually want to set the context to your custom object so that the scope of "this" is something more limited and useful than window.

The event subscriber can override the scope so that "this" refers to the custom object that was passed into the subscribe call.


1.カスタムイベントの定義


カスタムイベントの種類を定義するために、CustomEventのインスタンスを作ります

// カスタムオブジェクトのコンストラクタ
function TestObj(name) {
    this.name = name;
    // イベントの定義 ->CustomEventコンストラクタの呼び出し
    this.event1 = new YAHOO.util.CustomEvent("event1", this);
}

CustomEventコンストラクタが新しいカスタムイベントを作り2つの引数を受け取っています。
一つ目のパラメータは、イベントの種類です。この文字列がイベントを受け取るリスターに返されます。この文字列によってリスナーが何のイベントが起こったのかを判断できます。
二つ目のパラメータは、リスナーが呼び出されるスコープです。スコープのデフォルトは"window"です。が、カスタムオブジェクトを作ったのならカスタムオブジェクトにコンテクストを合わせたいものですね。スコープをカスタムオブジェクトに合わせる事で、"window"のスコープの時より"this"を制限的に使えます。

イベントの待ちうけ元は、スコープをオーバーライドできますので、"this"は、待ち受けもとの呼び出しに渡されることになるカスタムオブジェクトを参照します。??

2.Subscribing (Listening) to a Custom Event

To subscribe to a custom event, use the Subscribe method:

// a custom consumer object that will listen to "event1"
function Consumer(name, testObj) {
    this.name = name;
    this.testObj = testObj;
    this.testObj.event1.subscribe(this.onEvent1, this);
}

In this example, event1 is the custom event object that was created in the previous section. Use the Subscribe method to listen to that event. The Subscribe method takes two parameters. The first is the callback; the second is a custom object you can define (See Send an Arbitrary Object to the Event Handler). When the event is triggered the callback is called and the custom object is passed to that callback as the second argument (the first is the event type "event1").



2.カスタムイベントの待ち受け(リスニング)


カスタムイベントをキャッチするには、Suscribe()メソッドを使います

// "event1"をリッスンする(待ち構える)カスタムオブジェクト
//Consumerコンストラクタ
function Consumer(name, testObj) {
    this.name = name;
    this.testObj = testObj;
    this.testObj.event1.subscribe(this.onEvent1, this);
}

このサンプルの"event1"は前節で作ったカスタムイベントオブジェクトです。Subsribeメソッドをつかって、このイベントをリッスンします。Subscribe()メソッドは二つのパラメータをとります。
①コールバック関数
②自分で定義したカスタムオブジェクト(「イベントハンドラにはどんなオブジェクトでも渡せます」を見てください)
イベントが呼び出されると、コールバックが呼ばれ、カスタムオブジェクトはコールバック関数に二つの引数として渡されます。(一つ目の引数はイベントの種類"event1"です)

3.Creating a Callback

To create a callback for a custom event:

Consumer.prototype.onEvent1 = function(type, args, me) {
    alert(" this: " + this +
          "\n this.name: " + this.name +
          "\n type: " + type +
          "\n args: " + args +
          "\n me.name: " + me.name);
}

In this example the type argument is the event type ("event1" in this case), args is an array of all of the arguments that were passed to the custom event's fire mechanism, and me is the custom object we passed in when we subscribed to the event.


3.コールバックをつくる


カスタムイベントのコールバックを作ります

サンプルのtype引数はイベントの種類です(この場合"event1")argsはカスタムイベント発生機能?に渡される全部の引数を格納した配列です。meはイベントを待ち受けたときに渡すカスタムオブジェクトです。??

//プロトタイプメソッド ->インスタンスメソッドとしてのコールバック?
Consumer.prototype.onEvent1 = function(type, args, me) {
    alert(" this: " + this +
          "\n this.name: " + this.name +
          "\n type: " + type +
          "\n args: " + args +
          "\n me.name: " + me.name);
}

4.Triggering the Event

カスタムイベントを発生させる

To trigger or fire a custom event:

// random test data to be used as an event argument
function TestData(data) {
    this.data = data;
}

// create an instance of our test object
var t1 = new TestObj("mytestobj1");

// create the event consumer, passing in the custom 
// object so that it can subscribe to the custom event
var c1 = new Consumer("mytestconsumer1", t1);

// create a data object that will be passed to the consumer when the event fires
var d1 = new TestData("mydata1");

// fire the test object's event1 event, passing the data object as a parameter
t1.event1.fire(d1);

In this example t1 is the test object we created, event1 is the CustomEvent instance and d1 is our test data. This example produces the following output:

 this: [object Object]
 this.name: mytestobj1
 type: event1
 args: mydata1
 me.name: mytestconsumer1

*前節のサンプルと話が繋がってます。不明なプロパティやオブジェクトメソッドがあった場合、前の節のサンプルで定義されているかもしれないので気をつけてください。


カスタムイベントを発生させる

// イベントの引数になる適当なデータを作るコンストラクタ
function TestData(data) {
    this.data = data;
}

// テストオブジェクトのインスタンスを作る
var t1 = new TestObj("mytestobj1");

//カスタムイベントオブジェクトに渡すevent consumerオブジェクト
//カスタムイベントを待ち受けます

var c1 = new Consumer("mytestconsumer1", t1);

// イベントが起こった時、consumerオブジェクトに渡されるデータを作る
var d1 = new TestData("mydata1");

// event1イベントを発生させます。dataオブジェクトをパラメータとして渡す
t1.event1.fire(d1);

サンプルで、t1は自分で作ったテストオブジェクトです。event1はCustomEventインスタンスで、d1は自分で作ったテスト用のデータです。このサンプルの出力は以下のようになります

this: [object Object]
this.name: mytestobj1
type: event1
args: mydata1
me.name: mytestconsumer1