zoukankan      html  css  js  c++  java
  • 事件模块的演变(5)

    上一篇正式推出了我的事件模块event-v0.1,已经搭起了它的初始框架。或许有人要说,与众多JS库或框架相比,它还没有解决事件对象的兼容性问题。是的,我故意将此放到后续补充。因为事件对象的兼容性问题太多了,太繁琐了。

     

    这篇我将引入一个私有的_fixEvent函数,add中将调用该函数。_fixEvent将修复(或称包装)原生事件对象,返回一个标准的统一接口的事件对象。如下

    function _fixEvent( evt, el ) {
    	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;
    	function now() {return (new Date).getTime();}
    	function returnFalse() {return false;}
    	function returnTrue() {return true;}
    	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
    	};
    
    	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 ) ));
    	}		
    	if(!evt.currentTarget) evt.currentTarget = el;
    
    	return evt;
    }	
    

    好了,现在你要

    1,阻止事件默认行为,统一使用e.preventDefault()

    2,停止冒泡,统一使用e. stopPropagation()

    3,获取事件源,统一使用e.target

    ...


    更多的差异性,不在这一一列举了。请参考我在google doc上整理的文档:各浏览器中事件对象差异性列表。呃,不能FQ的同学抱歉了。以下是我的事件模块最终版功能

    1,最基本的添加、删除监听函数的事 

    function handle(){
    	//todo
    }
    E.add(document,'click',handle);
    E.remove(document,'click',handle);
    

    2,为同一个元素添加多个handle时,执行有序。所有浏览器中依次弹出1,2,3,4,5

    function handle1(){alert(1);}
    function handle2(){alert(2);}
    function handle3(){alert(3);}
    function handle4(){alert(4);}
    function handle5(){alert(5);}
    E.add(document,'click',handle1);
    E.add(document,'click',handle2);
    E.add(document,'click',handle3);
    E.add(document,'click',handle4);
    E.add(document,'click',handle5);
    

    3,添加仅执行一次的handler

    function handler(){
    	alert(1);
    }
    E.add(document,'click',handler,true);
    

    4,删除元素指定类型的所有handler

    function handle1(){
    	alert(1);
    }
    function handle2(){
    	alert(2);
    }
    E.add(document,'click',handle1);
    E.add(document,'click',handle2);
    
    E.remove(document,'click'); //删除了handle1和handle2
    

    5,删除附加元素上的所有handler

    function handle1(){
    	alert(1);
    }
    function handle2(){
    	alert(2);
    }
    E.add(document,'click',handle1);
    E.add(document,'mouseover',handle2);
    
    E.remove(document);
    

    6,主动触发事件。如模拟用户点击

    function handle(){
    	alert(1);
    }
    E.add(document,'click',handle);
    E.dispatch(document,'click'); 
    

    7,解决事件对象的兼容性问题,如阻止默认行为,停止冒泡等(支持DOM2/3 events)


    event-v0.2

  • 相关阅读:
    27_Go基础(defer)
    30_Go基础(接口)
    29_Go基础(结构体)
    关于PLSQL Developer报"动态执行表不可访问,本会话的自动统计被禁止"错的解决方法
    用JSP实现上传文件的两种方法
    rownum in ORACLE
    sql笔试语句大全
    oracle下载地址以及安装教程
    对于js中eval()函数的理解 和 写一个函数trim() 去掉字符串左右空格
    Java IO流 FileOutputStream类 和 FileInputStream类 FileReader类和FileWriter类
  • 原文地址:https://www.cnblogs.com/snandy/p/2010179.html
Copyright © 2011-2022 走看看