读jQuery之十三 添加事件和删除事件的核心方法

jQuery的事件模块严重依赖于其数据储存(jQuery.data),你会发现我的代码中的dataManager对象对应它。
这里只提供bind和unbind方法。暂不包含
1, 事件命名空间(event namespace)
2, 事件代理(event delegation)
3, 特殊事件如dom ready
接口如下:


代码如下:

E.bind(el, 'click', fn);
E.bind(el, 'click', fn, data);
E.unbind(el, 'click', fn);
E.unbind(el, 'click');
E.unbind(el);

代码如下:

/**
* Event from jQuery
* 2011-06-20 snandy
*
* A number of helper functions used for managing events.
* Many of the ideas behind this code originated from jQuery library (1.6.2).
*
* example
*
* E.bind(el, 'click', fn);
*
* E.bind(el, 'click', fn, data);
*
* E.unbind(el, 'click', fn);
*
* E.unbind(el, 'click');
*
* E.unbind(el);
*
*/
E = function( window ) {
var uuid = 0,
globalCache = {},
doc = window.document,
w3c = !!doc.addEventListener,
expando = 'snandy' + (''+Math.random()).replace(/\D/g, ''),
addListener = w3c ?
function(el, type, fn) { el.addEventListener(type, fn, false); } :
function(el, type, fn) { el.attachEvent('on' + type, fn); },
removeListener = w3c ?
function(el, type, fn) { el.removeEventListener(type, fn, false); } :
function(el, type, fn) { el.detachEvent('on' + type, fn); };
dispatch = w3c ?
function( el, type ){
try{
var evt = doc.createEvent('Event');
evt.initEvent( type, true, true );
el.dispatchEvent( evt );
}catch( e ){ alert( e ) };
} :
function( el, type ){
try{
el.fireEvent( 'on' + type );
}catch( e ){ alert( e ); }
},
dataManager = {
data : function ( elem, name, data ) {
var getByName = typeof name === "string",
thisCache,
isNode = elem.nodeType,
cache = isNode ? globalCache : elem,
id = isNode ? elem[ expando ] : elem[ expando ] && expando;
if(!id && isNode) {
elem[expando] = id = ++uuid;
}
if(!cache[id]){
cache[id] = {};
}
thisCache = cache[id];
if(data !== undefined) {
thisCache[name] = data;
}
return getByName ? thisCache[name] : thisCache;
},
removeData : function ( elem, name ) {
var id = elem[expando],
thisCache = globalCache[id];
if(!id || !thisCache){
return;
}
if(typeof name === 'string') {
delete thisCache[name];
}else{
delete globalCache[id];
}
}
};
function returnFalse() {
return false;
}
function returnTrue() {
return true;
}
function now() {
return (new Date).getTime();
}
function isEmptyObject( obj ){
for( var i in obj ){
return false;
}
return true;
}
function addEvent (elem, types, handler, data) {
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
return;
}
if ( handler === false ) {
handler = returnFalse;
} else if ( !handler ) {
return;
}
var elemData = dataManager.data( elem ),
events = elemData.events,
eventHandle = elemData.handle,
types = types.split(" ");
if ( !events ) {
elemData.events = events = {};
}
if ( !eventHandle ) {
elemData.handle = eventHandle = function ( e ) {
return evtHandle.call( eventHandle.elem, e );
};
}
eventHandle.elem = elem;
var type, i = 0;
while ( type = types[i++] ) {
var handleObj = {handler : handler, data : data},
handlers = events[type];
if ( !handlers ) {
handlers = events[type] = [];
addListener( elem, type, eventHandle );
}
handlers.push( handleObj );
}
elem = null;
}
function evtHandle ( event ) {
event = fixEvent( event || window.event );
var handlers = ((dataManager.data(this, "events") || {})[event.type] || []).slice(0);
event.currentTarget = this;
for( var j = 0, l = handlers.length; j < l; j++ ) {
var handleObj = handlers[j];
event.handler = handleObj.handler;
event.data = handleObj.data;
event.handleObj = handleObj;
var ret = handleObj.handler.call( this, event );
if( ret !== undefined ) {
if( ret === false ) {
event.preventDefault();
event.stopPropagation();
}
}
if( event.isImmediatePropagationStopped() ) {
break;
}
}
}
function removeEvent( elem, types, handler ) {
// don't do events on text and comment nodes
if( elem.nodeType === 3 || elem.nodeType === 8 ) {
return;
}
if( handler === false ) {
handler = returnFalse;
}
var type, origType, i = 0, j,
elemData = dataManager.data( elem ),
events = elemData && elemData.events;
if( !elemData || !events ) {
return;
}
// Unbind all events for the element
if( !types ) {
types = types || "";
for ( type in events ) {
removeEvent( elem, type );
}
return;
}
// Handle multiple events separated by a space
// jQuery(...).unbind("mouseover mouseout", fn);
types = types.split(" ");
while( (type = types[ i++ ]) ) {
origType = type;
handleObj = null;
eventType = events[ type ];
if( !eventType ) {
continue;
}
if( !handler ) {
for ( j = 0; j < eventType.length; j++ ) {
handleObj = eventType[ j ];
removeEvent( elem, origType, handleObj.handler );
eventType.splice( j--, 1 );
}
continue;
}
for( j = 0; j < eventType.length; j++ ) {
handleObj = eventType[ j ];
if( handler === handleObj.handler ) {
// remove the given handler for the given type
eventType.splice( j--, 1 );
}
}
}
// remove generic event handler if no more handlers exist
if ( eventType.length === 0 ) {
delete events[ origType ];
}
// Remove the expando if it's no longer used
if ( isEmptyObject( events ) ) {
var handle = elemData.handle;
if ( handle ) {
handle.elem = null;
}
delete elemData.events;
delete elemData.handle;
if ( isEmptyObject( elemData ) ) {
dataManager.removeData( elem, 'events' );
}
}
}
function Event( src ) {
this.originalEvent = src;
this.type = src.type;
this.timeStamp = now();
}
Event.prototype = {
preventDefault: function() {
this.isDefaultPrevented = returnTrue;
var e = this.originalEvent;
if( e.preventDefault ) {
e.preventDefault();
}
e.returnValue = false;
},
stopPropagation: function() {
this.isPropagationStopped = returnTrue;
var e = this.originalEvent;
if( e.stopPropagation ) {
e.stopPropagation();
}
e.cancelBubble = true;
},
stopImmediatePropagation: function() {
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
},
isDefaultPrevented: returnFalse,
isPropagationStopped: returnFalse,
isImmediatePropagationStopped: returnFalse
};
function fixEvent( evt ) {
var props = "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
len = props.length;
var originalEvent = evt;
evt = new Event(originalEvent);
for(var i = len, prop; i;) {
prop = props[ --i ];
evt[ prop ] = originalEvent[ prop ];
}
if(!evt.target) {
evt.target = evt.srcElement || document;
}
if( evt.target.nodeType === 3 ) {
evt.target = evt.target.parentNode;
}
if( !evt.relatedTarget && evt.fromElement ) {
evt.relatedTarget = evt.fromElement === evt.target ? evt.toElement : evt.fromElement;
}
if( evt.pageX == null && evt.clientX != null ) {
var doc = document.documentElement, body = document.body;
evt.pageX = evt.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
evt.pageY = evt.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
}
if( !evt.which && ((evt.charCode || evt.charCode === 0) ? evt.charCode : evt.keyCode) ) {
evt.which = evt.charCode || evt.keyCode;
}
if( !evt.metaKey && evt.ctrlKey ) {
evt.metaKey = evt.ctrlKey;
}
if( !evt.which && evt.button !== undefined ) {
evt.which = (evt.button & 1 ? 1 : ( evt.button & 2 ? 3 : ( evt.button & 4 ? 2 : 0 ) ));
}
return evt;
}
function bind ( el, type, fn, data ) {
var handler;
if( typeof type === "object" ) {
for( var key in type ) {
bind(el, key, type[key], data);
}
return;
}
handler = fn;
addEvent( el, type, handler, data );
}
function unbind ( el, type, fn ) {
if( typeof type === "object" ) {
for ( var key in type ) {
unbind( el, key, type[key] );
}
}else {
removeEvent( el, type, fn );
}
}
return {
data : dataManager.data,
removeData : dataManager.removeData,
bind : bind,
unbind : unbind
};
}(this);

(0)

相关推荐

  • jQuery编程中的一些核心方法简介

    调用 jQuery 对象的方法很简单: $('h1').remove(); 大多数 jQuery 方法都是像上面这样被调用的,这些方法都位于 $.fn 命名空间内,这些方法称为 jQuery 对象方法. 但是也有一些方法不需要依赖于选择器的结果集,这些方法位于 jQuery 命名空间内,这些方法称为 jQuery 核心方法.如果觉得不好理解,记住下面两条即可: 所有 jQuery 选择器的方法都位于 $.fn 命名空间内. $ 内的方法一般都是一些实用的功能性方法,这些方法不依赖选择器,这些方法

  • 读jQuery之十二 删除事件核心方法

    .remove 所作的事情与上一篇提到的.add 刚好相反.且与.add中的处理代码一一对应,即  .add 中有多少种添加事件的方式.remove就有对应的删除方式. .remove 定义了四个参数 elem, types, handler, pos .从字面上看四个参数的意义很明了 elem 为HTMLElement types 为String类型,事件名称如'click'或'mouseover mouseout' handler 为Function类型,事件回调函数 pos 为Number

  • 读jQuery之十四 (触发事件核心方法)

    在 事件模块的演变 我使用了dispatchEvent(标准) 和fireEvent(IE)来主动触发事件.如下 复制代码 代码如下: ... dispatch = w3c ? function(el, type){ try{ var evt = document.createEvent('Event'); evt.initEvent(type,true,true); el.dispatchEvent(evt); }catch(e){alert(e)}; } : function(el, typ

  • 读jQuery之十三 添加事件和删除事件的核心方法

    jQuery的事件模块严重依赖于其数据储存(jQuery.data),你会发现我的代码中的dataManager对象对应它. 这里只提供bind和unbind方法.暂不包含 1, 事件命名空间(event namespace) 2, 事件代理(event delegation) 3, 特殊事件如dom ready 接口如下: 复制代码 代码如下: E.bind(el, 'click', fn); E.bind(el, 'click', fn, data); E.unbind(el, 'click

  • jquery html动态添加的元素绑定事件详解

    在实际开发中会遇到要给动态生成的html元素绑定触发事件的情况: <div id="testdiv"> <ul></ul> </div> 假设我们要给ul动态添加的<li>绑定click事件形成如下结果 <div id="testdiv"> <ul> <li name="apple">apple</li> <li name="

  • jQuery给动态添加的元素绑定事件的方法

    本文实例讲述了jQuery给动态添加的元素绑定事件的方法.分享给大家供大家参考.具体分析如下: jquery中绑定事件一般使用bind,或者click,但是这只能是对已经加载好的元素定义事件,那些后来添加插入的元素则需要另行绑定.在1.7版本以前使用live.但是在1.8版本以后推荐使用on.这里介绍jQuery中如何给动态添加的元素绑定事件 在实际开发中会遇到要给动态生成的html元素绑定触发事件的情况 例如 <div id="testdiv"> <ul>&l

  • Java实现添加,读取和删除Excel图片的方法详解

    目录 介绍 Java 代码示例 示例1添加图片 示例2读取图片 示例3删除图片 介绍 本文介绍在Java程序中如何添加图片到excel表格,添加图片时可设置图片大小.位置.旋转.超链接.可选文本等,以及如何读取.删除excel表格中已有的图片. 工具:Free Spire.XLS for Java (免费版) 注:可通过官网下载包,并解压将lib文件夹下的jar文件导入java程序:或者通过maven仓库下载导入. Jar导入效果: Java 代码示例 示例1添加图片 import com.sp

  • 读jQuery之十一 添加事件核心方法

    这篇看看其源码,这个add定义如下(省略大部分) 复制代码 代码如下: add: function( elem, types, handler, data ) { if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } ... } 定义了四个参数elem.types.handler和data分别为HTMLElement.事件类型(如click).事件响应函数.数据.此外,types 可以以空格分开传多种事件("mouseover

  • 读jQuery之十 事件模块概述

    后面会详细分析jQuery.event.add/jQuery.event.remove/jQuery.event.trigger. 虽然事件模块代码很难读,但其提供的API接口还是很清晰的.如下 1 添加事件(bind/one/live/delegate/hover/toggle) bind 基本的添加事件函数. one 添加只执行一次的事件函数. live 事件代理(使用document代理). delegate 事件代理(使用指定元素代理). hover 模拟css的hover. toggl

  • jQuery实现动态添加、删除按钮及input输入框的方法

    本文实例讲述了jQuery实现动态添加.删除按钮及input输入框的方法.分享给大家供大家参考,具体如下: <html> <head> <meta charset="utf-8"> <title>动态创建按钮</title> <script src='http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js'></script> </head>

  • 读jQuery之八 包装事件对象

    比如,停止事件冒泡IE用 cancelBubble ,标准浏览器则用 stopPropagation . 获取事件源对象,IE用 srcElement ,标准浏览器则用 target 诸如此类. jQuery 对原生事件对象的修复和包装主要使用 jQuery.Event 类和 jQuery.event.fix 方法. 复制代码 代码如下: jQuery.Event = function( src ) { // Allow instantiation without the 'new' keywo

  • JavaScript实现跨浏览器的添加及删除事件绑定函数实例

    本文实例讲述了JavaScript实现跨浏览器的添加及删除事件绑定函数.分享给大家供大家参考.具体如下: IE 的事件绑定函数是 attachEvent:而 Firefox, Safari 是 addEventListener:Opera 则两种都支持.使用jQuery就可以使用简单的bind(),或者$().click()之类的函数解决,而如果不使用JavaScript框架的时候,大家可是使用下面的封装bind()函数. 添加事件绑定 bind() /*********************

随机推荐