今回は、jQuery.eventに関する処理の説明になります。ここしばらくは、ブラウザの差異を吸収するコードが続いていましたが、今回のエレメントに対してイベントを割り当てる処理の部分も良くできていて、参考になるような書き方がたくさん出てきます。
jQuery.event.add()
それでは、1795行目のコメント文から見ていきましょう。Dean Edwards氏のaddEventライブラリから多くのアイデアをもらっていると書かれています。IE7.jsや/packer/を公開されている方で、Dean Edwards: addEvent() - My Solutionに元になっているソースがあるので、興味がある方はこちらも合わせて読んでみてください。
1804行目からのjQuery.event.add()メソッドは、eventtype()、bind()、one() および bindReady()から呼び出され、実際にイベントを割り当てる内部処理用のメソッドです。1805行目で、引数elemに渡された要素のnodeTypeがテキストノードまたはコメントノードの場合には何もせずにreturnしています。
1810行目では、ブラウザがInternet Explorerの場合に発生する不具合対策のためにwindowオブジェクトのクローンを生成しています。
1814行目は、イベントハンドラに対してユニークなIDを生成しています。ここでいうhandlerというのは、実際に行われる処理を定義した関数のことです。
1818行目からは、引数dataが定義されている場合の処理で、イベントハンドラに対して引数dataをバインド(束縛)します。1823行目でhandlerをラップする関数を作成し、元々のhandlerに引数を渡すように再定義しています。これは、イベントの定義時ではなく、実行時のパラメータをhandlerに対してbindするためです。また、handler.dataにdataをhandler.guidに元のguidをそれぞれ設定します。
jQuery.handle
1836行目は、events変数の定義です。既にeventsが定義されていればその値を取得、なければ初期化します。
1837行目も同様で、既にhandleが定義されていればその値を取得、なければ新たに定義します。関数の中身は、1838~1848行目にて定義されています。1839行目でundefinedやfalseを返すために、戻り値用のval変数を定義します。そして、ページのアンロード時などjQuery変数が未定義の場合やネイティブイベントが実行中でjQuery.event.triggeredがtrueの場合には、undefinedを返します。
そうでなければ、applyメソッドを利用して関数を実行します。arguments.calleeは自身を指すので、arguments.callee.elemが実行時のthisになります。
1853行目は、handleのプロパティにelemを代入しています。コメントによると、Internet Explorerでのメモリリークを防ぐためのようです。
1857行目からは、イベントハンドラを登録する処理で、jQuery(...).bind("mouseover mouseout", fn); のようにイベント名をスペースで区切って、複数のイベントにハンドラを一括登録できます。処理としては、引数をスペースでsplitしてeach()でループしています。
1859行目は、引数type('click'などが入ります)を'.'で分割しています。これはどういうことかというと、次のようにclickイベントを割り当ててunbindするような処理で、もしclickイベントが複数割り当てられていたら、すべてのclickイベントが解除されてしまいます。
これを防ぐために、jQueryでは一連のイベントに対して名前を付けておくことができるようにしています。click.namespaceのように記述することでイベントを識別可能になります。
1860行目でブラウザが識別できるイベント名をtypeに格納し、1861行目でnamespaceをhandler.typeに格納します。
1864行目は現在割り当てられているイベントハンドラを取得します。そして、もし既に割り当てられているイベントがあれば、初期化を行います。2126行目以降で定義されているready, mouseenter, mouseleave以外なら、addEventListener/attachEventを使って実際に要素にイベントを割り当てます。
要素のハンドラーリストにハンドラー関数を登録し、後からどのイベントが使われているかを追跡するためにglobal[type]に格納しておきます。最後にInternet Explorerのメモリリーク対策のためにelemを空にします。
jQuery.event.remove()
1897行目からは、イベント登録を解除する処理になります。登録時と同様にテキストノードとコメントノードに対しては、何もせずにreturnします。
1902行目は、要素に割り当てられているイベントをeventsから取得します。同時にretとindexもローカル変数として宣言しておきます。
そして、もしイベントがみつかって、イベントの種類(引数types)が指定されていなければ、remove()を再帰的に呼び出し、すべてのイベントを解除します。
1911行目からは、types.typeが存在する場合、つまりtypesにイベントオブジェクトが与えられた場合の処理です。handlerおよびtypesの値をそれぞれtypesイベントのhandler、typeに設定し直します。
jQuery.remove()においても、複数のイベントを一括して解除できるようになっています。イベント登録時と同様に、スペースで複数イベントを解除し、'.'以降の名前空間を取り出してpartsおよびtypeに格納します。
1923行目からは、先ほど分割したtypeがeventsに存在する場合の処理になります。引数handlerが指定されていれば、deleteメソッドを使ってevents[type][handler.guid]オブジェクトを削除します。
handlerが指定されていなければ、events[type]に登録されている各handlerに対して、deleteメソッドを実行します。ただし、名前空間が指定されているイベント(click.namespaceように)の場合には、1932行目のif文によって該当するイベントのみを解除します。
1936行目のfor文と1937行目のif文にて、登録されたeventハンドラを調べます。もし、残っていなければ、2126行目以降で定義されているready, mouseenter, mouseleave以外のイベントをremoveEventListener/detachEventを使って要素からイベントを解除します。
1944行目でret変数の値をnullに設定し、events[type]オブジェクトを削除してこの部分は完了です。
1952行目のforループでeventsオブジェクトの中身を確認して、空であれば、最後にeventsとhandleのオブジェクトを削除します。