• 【前端】跨浏览器事件处理程序EventUtil.js个人注释及详解


    《javascript高级程序设计》跨浏览器事件处理程序EventUtil.js个人注释

    EventUtil.js

    // 跨浏览器事件处理程序封装
    var EventUtil = {
    	
    	// 添加事件句柄
    	addHandler: function(element, type, handler){
    		// DOM 2 级事件处理程序
    		if (element.addEventListener){
                element.addEventListener(type, handler, false);
            }
    		// IE事件处理程序
    		else if (element.attachEvent){
                element.attachEvent("on" + type, handler);
            } 
    		// DOM 0 级事件处理程序
    		else{
    			element["on" + type] = handler;
    		}
    	},
    
    	
    	// 获取鼠标事件button属性 ,
    	// 0:主鼠标按钮	
    	// 1:中间按钮		
    	// 2:次鼠标按钮
    	getButton: function(event){
    		// DOM Button属性
    		if(document.implementation.hasFeature("MouseEvents", "2.0")){
    			return event.button;
    		}
    		// IE 模式下的button属性
    		else{
    			switch(event.button){
                    case 0:
                    case 1:
                    case 3:
                    case 5:
                    case 7:
                        return 0;
                    case 2:
                    case 6:
                        return 2;
                    case 4: return 1;
                }
    		}
    	},
    
    
    	// 获取键盘事件keypress事件的charCode属性
    	// 该值表示按下的键所代表的ASCII码
    	getCharCode: function(event){
    		// IE9 FireFox Chrome Safari
    		if(typeof event.getCharCode == "number"){
    			return event.charCode;
    		}
    		// IE8 Opera
    		else{
    			return event.keyCode;
    		}
    	},
    
    
    	// 获取剪切板内容
    	getClipboardText: function(event){
            var clipboardData =  (event.clipboardData || window.clipboardData);
            return clipboardData.getData("text");
        },
    
        
        // 获取事件对象
        getEvent: function(event){
            return event ? event : window.event;
        },
    
        
        // 获取relatedTarget属性
        // 在mouseover事件触发时,IE的fromElement属性中保存了相关元素;
        // 在mouseout事件触发时,IE的toElement属性中保存了相关元素
        getRelatedTarget: function(event){
            // DOM属性,IE8不支持
            if (event.relatedTarget){
                return event.relatedTarget;
            } 
            // IE mouseout
            else if (event.toElement){
                return event.toElement;
            } 
            // IE mouseover
            else if (event.fromElement){
                return event.fromElement;
            } 
            else {
                return null;
            }
        
        },
        
    
        // 获取target事件对象
        getTarget: function(event){
        	// DOM || IE
            return event.target || event.srcElement;
        },
        
    
        // 获取鼠标滚轮滚动时的属性值
        getWheelDelta: function(event){
        	// IE6.0 Chrome  Opera  Safari wheelData属性值
        	// 向前滚动是120的倍数
        	// 向后滚动是-120的倍数
            if (event.wheelDelta){
                return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);
            } 
            // Firefox detail属性值
            // 向前滚动是-3的倍数
            // 向后滚动是3的倍数
            else {
                return -event.detail * 40;
            }
        },
        
    
        // 取消事件的默认行为
        preventDefault: function(event){
            // DOM
            if (event.preventDefault){
                event.preventDefault();
            } 
            // IE
            else {
                event.returnValue = false;
            }
        },
    
    
        // 移除事件句柄
        removeHandler: function(element, type, handler){
        	// DOM 2
            if (element.removeEventListener){
                element.removeEventListener(type, handler, false);
            } 
            // IE
            else if (element.detachEvent){
                element.detachEvent("on" + type, handler);
            } 
            // DOM 0
            else {
                element["on" + type] = null;
            }
        },
        
    
        // 设置剪切板内容
        setClipboardText: function(event, value){
        	// Chrome
            if (event.clipboardData){
                event.clipboardData.setData("text/plain", value);
            } 
            // IE
            else if (window.clipboardData){
                window.clipboardData.setData("text", value);
            }
        },
        
    
        // 取消事件冒泡
        stopPropagation: function(event){
        	// DOM
            if (event.stopPropagation){
                event.stopPropagation();
            }
            // IE
            else {
                event.cancelBubble = true;
            }
        }
    
    };
    

      

    详细说明:

    addHandler方法

    这是EventUtil中最常用的方法,它的作用是为对象添加事件并保证兼容性

    DOM0级事件处理程序(下文均简称“DOM0级”)中

    每个元素(包括windows和document)都有自己的事件处理程序属性(通常全部小写)

    如常见的onload、onclick等

    Click事件为例(下同),DOM0级通常如下指定事件处理程序

    1 var btn=document.getElementById("myBtn");
    2 btn.onclick=function(){ //指定事件处理程序
    3    alert(this.id);      //"myBtn"
    4 };

    DOM2级事件处理程序(下文均简称“DOM2级”)中

    指定事件处理程序的方法为addEventListener( )

    它接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值(大多数情况下是false)

    (布尔值表示是在捕获阶段(true)还是冒泡阶段(false)调用事件处理程序)

    DOM2级通常如下指定事件处理程序

    1 var btn=document.getElementById("myBtn");
    2 //在外部定义好函数再传给addEventListener(),这样才可以通过removeEventListener()移除
    3 var handler=function(){ 
    4    alert(this.id);
    5 };
    6 btn.addEventListener("click",handler,false);

    在旧版本IE(代表IE8-,下文均简称“IE”)中

    指定事件处理程序的方法为attachEvent( )

    它接受两个参数:事件处理程序名称与事件处理程序函数

    IE中通常如下指定事件处理程序

    1 var btn=document.getElementById("myBtn");
    2 var handler=function(){
    3    alert("Clicked");
    4 };
    5 //注意:第一个参数是"onclick",而非DOM0的addEventListener()方法中的"click"
    6 btn.attachEvent("onclick",handler);

    由上可见,DOM0级、DOM2级和IE中指定事件方法有很大不同

    EventUtil对象中的addHandler方法正是为了处理这些差异而存在

    在添加了EventUtil(指上文“EventUtil对象全见”中的代码,下同)后,可以如下所示为对象指定事件处理程序

    1 var btn=document.getElementById("myBtn");
    2 var handler=function(){
    3    alert("Clicked!");
    4 };
    5 EventUtil.addHandler(btn,"click",handler);  //调用已定义的EventUtil对象

    就像这样,使用addHandler方法指定事件处理程序

    即可兼容支持DOM0级、DOM2级的浏览器或IE浏览器

     

    removeHandler方法

    同样的,在DOM0级、DOM2级与IE中,移除事件的方法是不同的

    DOM0级中,在不再需要某对象的事件处理程序时(如页面销毁前),可以像下面这样简单的移除事件处理程序

    btn.onclick=null;

    DOM2级中,删除事件处理程序需要使用removeEventListener( )方法,如下所示

     1 //这里的handler应与使用addEventListener指定事件处理函数时所用的外部函数相同 

    2 btn.removeEventListener("click",handler,fals

    而在IE中,删除事件则需使用detachEvent( )方法

    btn.detachEvent("onclick",handler); 

    因为这些差异的存在,才令EventUtil中有了removeHandler方法

    在添加了EventUtil后,可以如下所示使用removeHandler方法方便地删除对象事件处理程序

    1 //同样的,这里的handler应与使用addHandler指定事件处理函数时所用的外部函数相同 

     2 EventUtil.removeHandler(btn,"click",hanlder);

    event对象与getEvent方法

    你可能已经发现了,在EventUtil中,很多方法的参数都是event

    这个event其实是事件对象

    兼容DOM(无论是DOM0级还是DOM2级)的浏览器会将一个event对象传入到事件处理程序中

    这个event对象支持许多方法,下表列出了一些常用的方法以供参考

    属性/方法类型读/写说明
    currentTarget Element 只读 其事件处理程序当前正在处理事件的那个元素
    preventDefault( ) Function 只读 取消事件的默认行为
    stopPropagation( ) Function 只读 取消事件的进一步捕获或冒泡
    target Element 只读 事件的实际(真正)目标
    type String 只读 被触发的事件的类型

    在兼容DOM的浏览器中,event对象可以如下面这个例子这样使用

     1 var btn=document.getElementById("myBtn");
     2 var handler=function(event){
     3    switch(event.type){      //使用event.type检测事件类型
     4       case "click":         //若是Click事件
     5          alert("Clicked");
     6          break;
     7       case: "mouseover":    //若是Mouseover事件
     8          //使用event.target获取事件目标,并更改目标样式背景颜色
     9          event.target.style.backgroundColor="red";
    10          break;
    11       case: "mouseout":     //若是Mouseout事件
    12          event.target.style.backgroundColor="";
    13          break;
    14    }
    15 };
    16 btn.onclick=handler;  //使用DOM0级为对象添加事件处理函数
    17 btn.onmouseover=handler;
    18 btn.onmouseout=handler;

    需要强调的是,以上使用event事件的方法仅适用于兼容DOM的浏览器

    在IE中则有所不同

    在IE中,使用DOM0级添加事件处理程序时,event对象作为window对象的一个属性存在,如下例子所示

    1 btn.onclick=function(){
    2    var event=window.event;
    3    alert(event.type);  //"click"
    4 };

    神奇的是,如果事件处理程序是使用attachEvent( )添加的,则又可以像在支持DOM的浏览器中一样

    event对象又可作为参数传入事件处理程序函数中,如下例子所示

    1 btn.attachEvent("onclick",function(event){ 2 alert(event.type); //"click" 3 }); 

    而且,更神奇的是,在IE中,event对象的一些属性/方法还跟其它支持DOM的浏览器中不同,如下表

    属性/方法类型读/写说明
    cancelBubble Boolean 读/写 默认值为false,将其设置为true就可以取消事件冒泡
    (与DOM中的stopPropagation( )方法的作用相同)
    returnValue Boolean 读/写 默认值为true,将其设置为false就可以取消事件的默认行为
    (与DOM中的preventDefault( )方法的作用相同)
    srcElement Element 只读 事件的目标(与DOM中的target属性相同)
    type String 只读 被触发的事件类型

    正是因为这些差异的存在,使得EventUtil中的getEvent方法应运而生

    在添加了EventUtil后,可以如下“重点语句”所示获取event对象而无需担心上述差异导致的兼容问题

    1 var btn=document.getElementById("myBtn");
    2 var handler=function(event){
    3    event=EventUtil.getEvent(event); //重点语句
    4 };
    5 EventUtil.addHandler(btn,"click",handler); 

    这样,就解决了event对象获取方式不同的问题

    至于event对象的属性/方法差异,下文还会介绍其它方法进行处理

     

    target对象与getTarget方法

    在上一部分(“event对象与getEvent方法”)的介绍中,通过表格你可能已经发现

    IE中和其它兼容DOM的浏览器中,获取事件目标(target)的方法不同

    IE中,获取事件目标对象的方法为event.srcElement

    而在其它兼容DOM的浏览器中,获取事件目标对象的方法却为event.target

    getTarget方法正是为了处理这个差异而存在

    在添加了EventUtil后,可以如下“重点语句”所示获取事件的目标(target)对象而无需担心上述差异导致的兼容问题

    1 var btn=document.getElementById("myBtn");
    2 var handler=function(event){
    3    event=EventUtil.getEvent(event); 
    4    var target=EventUtil.getTarget(event); //重点语句
    5 };
    6 EventUtil.addHandler(btn,"click",handler); 

    preventDefault方法

    在其它兼容DOM的浏览器中,阻止特定事件的默认行为只需使用event对象自带preventDefault( )方法,如下所示

    1 var link=document.getElementById("myLink");
    2 link.onclick=function(event){
    3    event.preventDefault(); //DOM0级或DOM2级阻止事件默认行为的方法
    4 }

    而在IE中,则需赋予event.returnValue的值为false才能阻止特定事件的默认行为

     1 link.attachEvent("onclick",function(event){ 2 event.returnValue=false; //IE中阻止事件默认行为的方法 3 }); 

    故在EventUtil中,存在一个preventDefault方法,用于统一上述差异

    在添加了EventUtil后,可以如下“重点语句”所示阻止特定事件的默认行为而无需担心上述差异导致的兼容问题

    1 var link=document.getElementById("myLink");
    2 var handler=function(event){
    3    event=EventUtil.getEvent(event);
    4    EventUtil.preventDefault(event); //重点语句
    5 };
    6 EventUtil.addHandler(link,"click",handler);

     

    stopPropagation方法

    有时候,我们需要取消事件的进一步捕获或冒泡,即停止事件在DOM层次中传播

    兼容DOM的浏览器可以通过使用event对象自带的stopPropagation( )方法做到这一点

    1 var link=document.getElementById("myLink");
    2 link.onclick=function(event){
    3    event.stopPropagation(); //DOM0级或DOM2级取消事件的进一步捕获或冒泡的方法
    4 };

    而在IE中,则需赋予event.cancelBubble的值为true

     1 link.attachEvent("onclick",function(event){ 2 event.cancelBubble=true; //IE中取消事件的进一步冒泡的方法 3 }); 

    EventUtil中的stopPropagation( )方法可以统一上述差异

    在添加了EventUtil后,可以如下“重点语句”所示取消事件的进一步捕获或冒泡而无需担心差异导致的兼容问题

    1 var link=document.getElementById("myLink");
    2 var handler=function(event){
    3    event=EventUtil.getEvent(event);
    4    EventUtil.stopPropagation(event); //重点语句
    5 };
    6 EventUtil.addHandler(link,"click",handler);

     

    相关元素与getRelatedTarget方法

    mouseover与mouseout有“主目标(主元素)”与“相关元素”的概念

    因为在发生mouseover或mouseout事件时,还会涉及到其它元素

    这两个事件都会涉及把鼠指针从一个元素(相关元素)移到另一个元素(主目标)内

    具体点说

    mouseover事件而言,事件的主目标是获得光标的元素,而相关元素是那个失去光标的元素

    mouseout事件而言,事件的主目标是失去光标的元素,而相关元素是那个获得光标的元素

    DOM通过event对象的relatedTarget属性提供了相关元素的信息

    IE8及之前的版本不支持relatedTarget属性,不过提供了其它类似属性支持

    mouseover事件触发时,IE的formElement属性中保存了相关元素

    mouseout事件触发时,IE的toElement属性中保存了相关元素

    EventUtil中的getRelatedTarget方法正是为了平衡这些差异而存在

    在添加了EventUtil后,可以像下面示例“重点语句”一样使用getRelatedTarget方法

    1 var div=document.getElementById("myDiv");
    2 EventUtil.addHandler(div,"mouseout",function(event){
    3    event=EventUtil.getEvent(event);
    4    var target=EventUtil.getTarget(event);
    5    var relatedTarget=EventUtil.getRelatedTarget(event); //重点语句
    6    alert("鼠标离开了"+target.tagName+"元素而进入了"+relatedTarget.tagName+"元素");
    7 });

     

    getButton方法

    我们知道,只有在鼠标主按钮被单击(或键盘回车键被按下、触摸屏被单点击中)时才会触发click事件

    但对于mousedown和mouseup事件来说,鼠标上的任意按钮都可以触发它

    有时,我们可能需要知道用户按下了哪个鼠标按钮

    DOM的event.button属性可以做到这一点,这个属性可能有3个值

    0表示主鼠标按钮(通常是左键)、1表示鼠标滚轮按钮、2表示鼠标右键

    虽然IE的event对象也提供了button属性

    但遗憾的是,IE的button属性与DOM的button属性有很大差异

    而且不被其它浏览器支持,实用性很低,在此不予赘述

    getButton方法的作用是,让所有浏览器的event.button表现与DOM相同

    在添加了EventUtil后,可以像下面示例“重点语句”一样使用getButton方法而无需考虑IE中的差异

    1 var div=document.getElementById("myDiv");
    2 EventUtil.addHandler(div,"mousedown",function(event){ //监控按下div的是哪个按钮
    3    event=EventUtil.getEvent(event);
    4    alert(EventUtil.getButton(event));  //重点语句,弹出框显示按下哪个鼠标键的代号(0、1或2)
    5 });
    6 //同理,若事件是mouseup,则botton值表示释放的是哪个按钮

     

    getWheelDelta方法

    有时,为了让页面达到某些特殊效果,我们需要监视用户的鼠标滚轮操作

    这一次,“与众不同”的是Firefox,而不是旧版本的IE

    所有浏览器(包括IE6,除了Firefox)均支持鼠标滚轮事件mousewheel

    Firefox却是通过DOMMouseScroll事件实现类似功能

    事件名的差异无法通过EventUtil改变

    但关键是,这个事件表示鼠标滚轮滚动方向的方法,Firefox与其它浏览器也有差异

    差异的本身已不是重点,重点是EventUtil的getWheelDelta方法可以很好的解决它们的差异

    在添加了EventUtil后,可以像下面示例“重点语句”一样使用getWheelDelta方法而无需考虑FIrefox中的差异

    1 function handleMouseWheel(event){
    2    event=EventUtil.getEvent(event);
    3    var delta=EventUtil.getWheelDelta(event);  //重点语句,delta是表示鼠标滚轮滚动方向的数值
    4    alert(delta);
    5 }
    6 EventUtil.addHandler(document,"mousewheel",handleMouseWheel);      //非Firefox
    7 EventUtil.addHandler(document,"DOMMouseScroll",handleMouseWheel);  //Firefox

    多数情况下,我们只需关心如上例中通过getWheelDelta方法获得的delta数值的正负

    当用户向前滚动鼠标滚轮时,delta的数值为正,反之为负

    滚轮滚动越多,delta数值的绝对值越大,且均是120的倍数

     

    getCharCode方法

    在所有浏览器中,按下能够插入或删除的字符的按键都会触发keypress事件

    IE8-及Opera取得字符编码(ASCII码)的方式与其它浏览器是不同的

    为了解决这一差异,在EventUtil中存在getCharCode方法

    在添加了EventUtil后,可以像下面示例“重点语句”一样使用getCharCode方法来获取统一的字符编码

    1 var textbox=document.getElementById("myText");
    2 EventUtil.addHandler(textbox,"keypress",function(event){
    3    event=EventUtil.getEvent(event);
    4    alert(EventUtil.getCharCode(event)); //重点语句,弹出窗口中显示按下按键代表字符的ASCII码
    5 });
  • 相关阅读:
    postgresql字符串函数
    ruby中的设计模式--策略模式
    (转)MySQL 性能优化的最佳20多条经验分享
    (转)ruby中的设计模式--模板方法
    观察者模式的应用
    postgresql的ARRAY_TO_STRING
    ruby和javascript的观察者模式
    mysql表连接的时候注意事项
    checkbox记忆功能的实现
    order by的注意事项
  • 原文地址:https://www.cnblogs.com/dragonir/p/7805818.html
Copyright © 2020-2023  润新知