win.gevent = {
handle : function(event){
var all, handlers;
//包裝event
event = arguments[0] = gevent.fix( event || window.event );
event.currentTarget = this;
//這里的........
var namespaces = event.type.split(".");
event.type = namespaces.shift();
all = !namespaces.length;
var namespace = RegExp("(^|//.)" + namespaces.slice().sort().join(".*//.") + "(
//.|$)");
//取這個元素的該行為 的 事件列表
handlers = (data(this, "events") || {} )[event.type];
//遍歷這個事件列表 執行該執行的東西
for ( var j in handlers ) {
var handler = handlers[j];
if ( all || namespace.test(handler.type) ) {
// Pass in a reference to the handler function itself
// So that we can later remove it
// jq上的注釋是是這么寫的 把event的handler 引用這個事件 方便之后移除
// 但是在remove里面 并沒有用到event的handler 不知道這里到底有什么用 且有多個事件的時候這個事件被取代
event.handler = handler;
//執行事件 并且是用元素調用的事件 可以吧事件里面的this執行元素 ret為函數的返回值
var ret = handler.apply(this, arguments);
//如果有返回值 且返回值是false 執行阻止事件冒泡 阻止執行事件默認行為
if( ret !== undefined ){
event.result = ret;
if ( ret === false ) {
event.preventDefault();
event.stopPropagation();
}
}
}
}
},
props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix : function(event){
//new setEvent會給event給以個expando屬性 如果有中個屬性 說明已經生成了event了 不需要在次對event進行包裝
if ( event[expando] )
return event;
//保留一個原始的event
// new一個新的event 這個與原始的event是不同的
var originalEvent = event;
event = new setEvent( originalEvent );
//獲得原始event的屬性值 有哪些屬性值 見 this.props
for ( var i = this.props.length, prop; i; ){
prop = this.props[ --i ];
event[ prop ] = originalEvent[ prop ];
}
//將目標元素同一成event.target
if ( !event.target )
event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
//如果發現是文本節點 取他的父節點
if ( event.target.nodeType == 3 )
event.target = event.target.parentNode;
if ( !event.relatedTarget && event.fromElement )
event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
return event;
}
}
win.setEvent = function(src){
// Allow instantiation without the 'new' keyword
// Event object
if( src && src.type ){
this.originalEvent = src;
this.type = src.type;
// Event type
}else
this.type = src;
// timeStamp is buggy for some events on Firefox(#3843)
// So we won't rely on the native value
this.timeStamp = now();
// Mark it as fixed
this[expando] = true;
}
function returnFalse(){
return false;
}
function returnTrue(){
return true;
}
setEvent.prototype = {
preventDefault: function() {
var e = this.originalEvent;
if( !e )
return;
// if preventDefault exists run it on the original event
if (e.preventDefault)
e.preventDefault();
// otherwise set the returnValue property of the original event to false (IE)
e.returnValue = false;
},
stopPropagation: function() {
var e = this.originalEvent;
if( !e )
return;
// if stopPropagation exists run it on the original event
if (e.stopPropagation)
e.stopPropagation();
// otherwise set the cancelBubble property of the original event to true (IE)
e.cancelBubble = true;
},
stopImmediatePropagation:function(){
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
},
isImmediatePropagationStopped: returnFalse
};
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
<html xmlns="
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title></title>
</head>
<body>
<div id="vv" style="height:200px;width:200px; background-color:#f00; padding:20px;">
<div id="xx" style="height:200px;width:200px; background-color:#000000;"></div>
</div>
<script type="text/javascript">
(function(doc,undefined){
function now(){
return +new Date;
};
var win = this,
expando = "jQuery" + now(),
uuid = 0,
cache = {};
win.data = function(elem, name, data){
var id = elem[expando];
if(!id)
id = elem[expando] = ++uuid;
if(name&&!cache[id])
cache[id] = {};
if(data !== undefined)
cache[id][name] = data;
return name
? cache[id][name]
: id;
}
win.removeData = function(elem, name){
var id = elem[expando];
if (name){
if (cache[id]) {
delete cache[id][name];
name = "";
for ( name in cache[ id ] )
break;
if ( !name )
removeData(elem);
}
}else{
try {
delete elem[expando];
} catch(e){
if ( elem.removeAttribute )
elem.removeAttribute( expando );
}
delete cache[id];
}
}
win.each = function( object, callback, args ) {
var name, i = 0, length = object.length;
if ( args ) {
if ( length === undefined ) {
for ( name in object )
if ( callback.apply( object[ name ], args ) === false )
break;
} else
for ( ; i < length; )
if ( callback.apply( object[ i++ ], args ) === false )
break;
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
for ( var value = object[0];
i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
}
return object;
}
win.gevent = {
guid : 1,
add : function (elem, types, handler){
if ( elem.nodeType == 3 || elem.nodeType == 8 )
return;
if ( elem.setInterval && elem != window )
elem = window;
//給函數一個唯一標識的索引 方便后面刪除該事件
if ( !handler.guid )
handler.guid = this.guid++;
//獲得該元素的events handle 下的數據
var events = data(elem, "events") || data(elem, "events", {}),
handle =data(elem, "handle") || data(elem, "handle", function(){
//gevent.handle才是各種行為觸發后會執行的函數
gevent.handle.apply(arguments.callee.elem, arguments);
});
handle.elem = elem;
//遍歷事件名 因為可以是 click mouseover
each(types.split(//s+/), function(index, type) {
var namespaces = type.split(".");
//獲得事件名
type = namespaces.shift();
//去掉點后面的東西 是個特殊的命名 在刪除的時候可以指定刪除他 如 click.d
//用事件的type 記錄住這個特殊的命名
handler.type = namespaces.slice().sort().join(".");
//獲得該事件是否已經存在events 這個對象里面了
var handlers = events[type];
//如果不存在該事件 給元素綁定該事件
if (!handlers) {
handlers = events[type] = {};
if (elem.addEventListener)
elem.addEventListener(type, handle, false);
else if (elem.attachEvent)
elem.attachEvent("on" + type, handle);
}
//吧函數放到元素的該事件的列表里面
handlers[handler.guid] = handler;
});
elem = null;
},
remove: function(elem, types, handler) {
if ( elem.nodeType == 3 || elem.nodeType == 8 )
return;
//獲取這個元素的所有行為列表 如 {click:{},mouseocer:{}}
var events = data(elem, "events"), ret, index;
if(events){
//如果沒出入行為類型 則刪除這個元素的所有事件
//如果傳入的是.xx這種形式的 把所有行為的包含.xx命名的全部干掉
if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") ){
for ( var type in events )
this.remove( elem, type + (types || "") );
}else{
//不知道干嘛的
if ( types.type ) {
handler = types.handler;
types = types.type;
}
//因為刪除事件可以一次支持刪除多個 如click mouseover 所有要遍歷刪除
each(types.split(//s+/),function(index, type){
var namespaces = type.split(".");
type = namespaces.shift();
var namespace = RegExp("(^|//.)" + namespaces.slice().sort().join(".*//.") + "(
//.|$)");
if ( events[type] ) {
//如果傳了第3個參數 函數 則刪除這個事件
if ( handler )
delete events[type][handler.guid];
else{
//遍歷中個這個的所有行為
for ( var handle in events[type] ){
// Handle the removal of namespaced events
//刪除有特殊命名的函數
//如果沒有特殊命名 正則 則是/^|..|$/ 可以匹配空 所以也能刪除掉沒有特殊命名的函數
if ( namespace.test(events[type][handle].type) )
delete events[type][handle];
}
}
}
for ( ret in events[type] ) break;
//如果events[type]變成空的了 也就是{} 刪除這個元素的的綁定事件
if ( !ret ) {
if (elem.removeEventListener)
elem.removeEventListener(type, data(elem, "handle"), false);
else if (elem.detachEvent)
elem.detachEvent("on" + type, data(elem, "handle"));
ret = null;
delete events[type];
}
});
}
for ( ret in events ) break;
//如果發現元素的整個events都是空的了
//清空掉handle 并且清空掉他所有的引用
if ( !ret ) {
var handle = data( elem, "handle" );
if ( handle ) handle.elem = null;
removeData( elem, "events" );
removeData( elem, "handle" );
}
}
},
handle : function(event){
var all, handlers;
//包裝event
event = arguments[0] = gevent.fix( event || window.event );
event.currentTarget = this;
//這里的........
var namespaces = event.type.split(".");
event.type = namespaces.shift();
all = !namespaces.length;
var namespace = RegExp("(^|//.)" + namespaces.slice().sort().join(".*//.") + "(
//.|$)");
//取這個元素的該行為 的 事件列表
handlers = (data(this, "events") || {} )[event.type];
//遍歷這個事件列表 執行該執行的東西
for ( var j in handlers ) {
var handler = handlers[j];
if ( all || namespace.test(handler.type) ) {
// Pass in a reference to the handler function itself
// So that we can later remove it
// jq上的注釋是是這么寫的 把event的handler 引用這個事件 方便之后移除
// 但是在remove里面 并沒有用到event的handler 不知道這里到底有什么用 且有多個事件的時候這個事件被取代
event.handler = handler;
//執行事件 并且是用元素調用的事件 可以吧事件里面的this執行元素 ret為函數的返回值
var ret = handler.apply(this, arguments);
//如果有返回值 且返回值是false 執行阻止事件冒泡 阻止執行事件默認行為
if( ret !== undefined ){
event.result = ret;
if ( ret === false ) {
event.preventDefault();
event.stopPropagation();
}
}
}
}
},
props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix : function(event){
//new setEvent會給event給以個expando屬性 如果有中個屬性 說明已經生成了event了 不需要在次對event進行包裝
if ( event[expando] )
return event;
//保留一個原始的event
// new一個新的event 這個與原始的event是不同的
var originalEvent = event;
event = new setEvent( originalEvent );
//獲得原始event的屬性值 有哪些屬性值 見 this.props
for ( var i = this.props.length, prop; i; ){
prop = this.props[ --i ];
event[ prop ] = originalEvent[ prop ];
}
//將目標元素同一成event.target
if ( !event.target )
event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
//如果發現是文本節點 取他的父節點
if ( event.target.nodeType == 3 )
event.target = event.target.parentNode;
if ( !event.relatedTarget && event.fromElement )
event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
return event;
}
}
win.setEvent = function(src){
// Allow instantiation without the 'new' keyword
// Event object
if( src && src.type ){
this.originalEvent = src;
this.type = src.type;
// Event type
}else
this.type = src;
// timeStamp is buggy for some events on Firefox(#3843)
// So we won't rely on the native value
this.timeStamp = now();
// Mark it as fixed
this[expando] = true;
}
function returnFalse(){
return false;
}
function returnTrue(){
return true;
}
setEvent.prototype = {
preventDefault: function() {
var e = this.originalEvent;
if( !e )
return;
// if preventDefault exists run it on the original event
if (e.preventDefault)
e.preventDefault();
// otherwise set the returnValue property of the original event to false (IE)
e.returnValue = false;
},
stopPropagation: function() {
var e = this.originalEvent;
if( !e )
return;
// if stopPropagation exists run it on the original event
if (e.stopPropagation)
e.stopPropagation();
// otherwise set the cancelBubble property of the original event to true (IE)
e.cancelBubble = true;
},
stopImmediatePropagation:function(){
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
},
isImmediatePropagationStopped: returnFalse
};
})(document);
var $ = function(id){return document.getElementById(id)}
var a = function(){alert(1)}
window.onload = function(){
gevent.add($('xx'),'click',a);
gevent.add($('xx'),'click',function(){alert(1)});
gevent.add($('xx'),'click',function(){alert(2)});
gevent.add($('xx'),'click',function(){alert(3)});
gevent.add($('xx'),'click.xx',function(){alert(4)});
}
</script>
</body>
</html>
以上內容只是自己的一些理解,水平有限,難免有錯,望指正...