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

  • 相关阅读:
    (转载)C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
    网络编程前奏(三)
    Linux学习之第三课时--Linux目录
    Linux学习之第二课时--linux命令格式及命令概述
    Linux学习之第一课时--linux前生今世
    python学习之第十四课时--基本数据练习
    python学习之第十三课时--其他数据类型,其他
    python学习之第十二课时--基本数据类型(set)
    python学习之第十一课时--基本数据类型(dict)
    python学习之第十课时--基本数据类型(tuple)
  • 原文地址:https://www.cnblogs.com/snandy/p/2010179.html
Copyright © 2011-2022 走看看