jQuery event.js 1回

event.js 1回目のメモを公開しますー遅れてすんません。 毎度おなじみ@ryuoneさんの記事はこちら →jQuery event.js 読書会 1回目に参加しました。

では1行目から バージョンは1.6.1です。

(function( jQuery ) {
	// hasOwnPropertyへのエイリアス
var hasOwn = Object.prototype.hasOwnProperty,

	rnamespaces = /\.(.*)$/,
	// \.でドット
	// ()でキャプチャグループ
	// .は任意の文字
	// *は0回以上の繰り返し
	// $は(.*)で最後の意味

	rformElems = /^(?:textarea|input|select)$/i,
	// ^(ハット)は最初の意味
	// (?:)は非キャプチャグループ textarea もしくは input もしくは select
	// 上記で終わる
	// iフラグは大文字と小文字を区別しない

	rperiod = /\./g,
	// \.でドット
	// g 繰り返しマッチ (メソッドによって異なる)

	rspaces = / /g,
	// 空白

	rescape = /[^\w\s.|`]/g,
	// \w 英数字
	// \s空白文字
	// .は任意の一文字
	// `は単なる文字
	// [^]は~以外という意味 \w\s.|`以外という意味

	// マッチしたものの先頭に\をつける
	fcleanup = function( nm ) {
		return nm.replace(rescape, "\\$&");
	};
	
	// String.replace()は第2引数に関数を渡したりもできる!

	//===================
	// $について
	//===================
	// $1 = 第1キャプチャグループ
	// $2 = 第2キャプチャグループ
	// $3,$4 ...
	// $0 検索対象すべて
	// $& マッチしたすべて

/*
 * A number of helper functions used for managing events.
 * Many of the ideas behind this code originated from
 * Dean Edwards' addEvent library.
 */

jQuery.event = {
	// Bind an event to an element
	// Original by Dean Edwards
	// "jQuery.fn.bind()やjQuery.fn.one()"などから呼ばれる。
	// イベントの登録

	add: function( elem, types, handler, data ) {
		// 第2引数のtypesはイベントのタイプ ( click,mouseover など )
		// 第3引数のhandlerはコールバック関数

		// テキストもしくはコメントであれば何もしない
		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
			return;
		}

		// 第3引数handlerがfalseの場合
		if ( handler === false ) {
			// returnFalseは601行目で定義
			// handler()とするとfalseを返す
			handler = returnFalse;

		// handlerがない場合 ここから
		} else if ( !handler ) {
			// Fixes bug #7229. Fix recommended by jdalton
			return;
		}
		// handlerがない場合 ここまで

		var handleObjIn, handleObj;

		// handlerがhandlerプロパティを持っていれば
		// (handlerがhandlerプロパティを持つときってどんなときやろ)
		if ( handler.handler ) {
			handleObjIn = handler;
			// handler.handlerをhandlerにする
			handler = handleObjIn.handler;
		}

		// Make sure that the function being executed has a unique ID
		// guidを持っていなければユニークキーを追加する
		if ( !handler.guid ) {
			handler.guid = jQuery.guid++;
		}

		// Init the element's event structure
		// jQuery._dataはdata.jsで定義
		// jQuery.data()の内部利用版
		// 引数が1つの場合はelemのdataを取ってくる
		var elemData = jQuery._data( elem );

		// If no elemData is found then we must be trying to bind to one of the
		// banned noData elements
		//dataが利用出来なかった場合
		if ( !elemData ) {
			return;
		}

		var events = elemData.events,
			eventHandle = elemData.handle;

		if ( !events ) {
			elemData.events = events = {};
		}

		// elemDataそのものがない
		// handleがないなどの場合定義
		if ( !eventHandle ) {
			elemData.handle = eventHandle = function( e ) {
				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
					jQuery.event.handle.apply( eventHandle.elem, arguments ) :
					undefined;
			};
		}

		// Add elem as a property of the handle function
		// This is to prevent a memory leak with non-native events in IE.

		eventHandle.elem = elem;

		// Handle multiple events separated by a space
		// jQuery(...).bind("mouseover mouseout", fn);
		
		// イベントの種類
		types = types.split(" ");

		var type, i = 0, namespaces;

		// イベントの数だけまわす
		// $().bind("myEvent myEvent2",function(){});
		// とかすると2回
		while ( (type = types[ i++ ]) ) {
			handleObj = handleObjIn ?
				jQuery.extend({}, handleObjIn) :
				{ handler: handler, data: data };
			// 1回目は絶対後方
			// handleObj = { handler: handler, data: data };

			// Namespaced event handlers
			// 名前空間の処理
			if ( type.indexOf(".") > -1 ) {
				// shift.click
				namespaces = type.split(".");
				type = namespaces.shift();
				// shiftは先頭の値を得る。
				// sliceで新しく配列を作ってソートして"."でつなぐ
				handleObj.namespace = namespaces.slice(0).sort().join(".");

			} else {
				// typeに名前空間がなければ
				namespaces = [];
				handleObj.namespace = "";
			}

			handleObj.type = type;
			// 初めて定義された場合とか
			if ( !handleObj.guid ) {
				handleObj.guid = handler.guid;
			}

			// Get the current list of functions bound to this event
			var handlers = events[ type ],
				// special はここで宣言。
				// jQuery.event.special 519行目
				// specialのプロパティのイベントであれば値を入れる。なければからのobj
				// プロパティは
				// beforeunload, focusin, focusout, live, mouseenter
				// mouseleave, ready
				special = jQuery.event.special[ type ] || {};

			// Init the event handler queue
			// 初めてイベントを登録する場合
			if ( !handlers ) {
				handlers = events[ type ] = [];

				// Check for a special event handler
				// Only use addEventListener/attachEvent if the special
				// events handler returns false
				// special.setupは
				// special.add.setupとかbeforeunload.setupとか
				// setupが出来ない状態
				// 詳しくは519行目 specialオブジェクトを参照
				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
					// Bind the global event handler to the element
					if ( elem.addEventListener ) {
						elem.addEventListener( type, eventHandle, false );

					} else if ( elem.attachEvent ) {
						elem.attachEvent( "on" + type, eventHandle );
					}
				}
			}

			// addがあるspecialのプロパティ
			if ( special.add ) {
				special.add.call( elem, handleObj );

				if ( !handleObj.handler.guid ) {
					handleObj.handler.guid = handler.guid;
				}
			}

			// Add the function to the element's handler list
			handlers.push( handleObj );

			// Keep track of which events have been used, for event optimization
			// 144行目 からのオブジェクト
			jQuery.event.global[ type ] = true;
		}

		// Nullify elem to prevent memory leaks in IE
		elem = null;
	},
	// ↑↑addメソッドここまで↑↑
	
	global: {},
	
	// Detach an event or set of events from an element
	// 消してるだけ
	remove: function( elem, types, handler, pos ) {
		// don't do events on text and comment nodes
		// テキストかコメントであればなにもしない
		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
			return;
		}

		if ( handler === false ) {
			handler = returnFalse;
		}

		// 見やすいように改行にします。
		var ret,
			type,
			fn,
			j,
			i = 0,
			all,
			namespaces,
			namespace,
			special,
			eventType,
			handleObj,
			origType,
			// あとで確認
			elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
			events = elemData && elemData.events;

		if ( !elemData || !events ) {
			return;
		}

		// types is actually an event object here
		// undefinedのプロパティを評価しようとしたら例外が発生するため
		if ( types && types.type ) {
			handler = types.handler;
			types = types.type;
		}

		// Unbind all events for the element
		//typesがない場合、ドットから始まる場合はもう一度呼びなおす
		if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
			types = types || "";

			for ( type in events ) {
				jQuery.event.remove( elem, type + types );
			}

			return;
		}

		// Handle multiple events separated by a space
		// jQuery(...).unbind("mouseover mouseout", fn);
		types = types.split(" ");

		while ( (type = types[ i++ ]) ) {
			origType = type;
			handleObj = null;
			all = type.indexOf(".") < 0;
			namespaces = [];

			// typeにドットが含まれていれば
			if ( !all ) {
				// Namespaced event handlers
				namespaces = type.split(".");
				type = namespaces.shift();

				// namespaceの正規表現を作ってる
				// こんんあやりかたあるんですねぇ
				namespace = new RegExp("(^|\\.)" +
					jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
			}

			eventType = events[ type ];

			if ( !eventType ) {
				// 次の処理へ
				continue;
			}

			if ( !handler ) {
				for ( j = 0; j < eventType.length; j++ ) {
					handleObj = eventType[ j ];

					if ( all || namespace.test( handleObj.namespace ) ) {
						jQuery.event.remove( elem, origType, handleObj.handler, j );
						eventType.splice( j--, 1 );
					}
				}

				continue;
			}

			// 消すための条件を一致させていくための処理
			
			special = jQuery.event.special[ type ] || {};

			// pos 数字
			// eventType.lengthは毎回評価
			for ( j = pos || 0; j < eventType.length; j++ ) {
				handleObj = eventType[ j ];

				if ( handler.guid === handleObj.guid ) {
					// remove the given handler for the given type
					if ( all || namespace.test( handleObj.namespace ) ) {
						if ( pos == null ) {
							// 後置なので0-1
							// 鉛筆削り
							eventType.splice( j--, 1 );
						}

						if ( special.remove ) {
							special.remove.call( elem, handleObj );
						}
					}

					// position指定したらもういいので1回だけで終了
					if ( pos != null ) {
						break;
					}
				}
			}

			// remove generic event handler if no more handlers exist
			if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
				// teardown は
				// ここで消す
				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
					jQuery.removeEvent( elem, type, elemData.handle );
				}

				ret = null;
				delete events[ type ];
			}
		}
		// typeを全部見ていって消していく

		// Remove the expando if it's no longer used
		if ( jQuery.isEmptyObject( events ) ) {
			var handle = elemData.handle;
			if ( handle ) {
				handle.elem = null;
			}

			delete elemData.events;
			delete elemData.handle;

			if ( jQuery.isEmptyObject( elemData ) ) {
				jQuery.removeData( elem, undefined, true );
			}
		}
	},
  • 2011/06/25
  • jsdokusho

コメントを書く

お名前[必須]

メールアドレス[必須]メールアドレスは公開されません。

コメント

トラックバック/ピンバック

トラックバック URL