跨浏览器事件对象封装

封装一个能够隔离浏览器差异的JavaScript库EventUtil,主要是使用能力检测。

var EventUtil={
    addHandler:function(element,type,handler){
        if(element.addEventListener){ 
            element.addEventListener(type,handler,false);
        }else if(element.attachEvent){
            element.attachEvent('on'+type,handler);
        }else{
            element['on'+type]=handler;
        }
    },
    getEvent:function(event){
        return event?event :window.event;
    },
    getTarget:function(){
        return event.target | event.srcElement;
    },
    preventDefault:function(event){
        if(event.preventDefault){
            event.preventDefault();
        }else{
            event.returnValue=false;
        }
    },
    removeHandler:function(element,type,handler){
        if(element.removeEventListener){
            element.removeEventListener(type,handler,false);
        }else if(element.detachEvent){
            element.detachEvent('on'+type,handler);
        }else{
            element['on'+type]=null;
        }
    },
    stopPropagation:function(event){
        if(event.stopPropagation){
            event.stopPropagation();
        }else{
            event.cancelBubble=true;
        }
    }
};
View Code

 

一、跨浏览器的事件处理程序

要保证处理事件的代码在大多数浏览器下一致运行,只需要关注冒泡阶段。

1、添加事件:addHandler

//添加事件
    /*
    element:要操作的元素
    type:事件名称
    handler:事件处理程序函数
    */
    addHandler:function(element,type,handler){
        if(element.addEventListener){ //存在DOM2级方法,则使用并传入事件类型、事件处理程序函数和第3个参数false(表示冒泡阶段)
            element.addEventListener(type,handler,false);
        }else if(element.attachEvent){//为兼容IE8及更早浏览器,注意事件类型必须加上"on"前缀
            element.attachEvent('on'+type,handler);
        }else{
            element['on'+type]=handler;//其他方法都无效,默认采用DOM0级方法,使用方括号语法将属性名指定为事件处理程序
        }
    }

2、删除事件

//移除addHandler添加的事件处理程序
/*
element:要操作的元素
type:事件名称
handler:事件处理程序函数
*/
removeHandler:function(element,type,handler){
    if(element.removeEventListener){
        element.removeEventListener(type,handler,false);
    }else if(element.detachEvent){
        element.detachEvent('on'+type,handler);
    }else{
        element['on'+type]=null;
    }
}
View Code

 二、跨浏览器事件处理

1、获取事件

返回event对象的引用

getEvent:function(event){
        return event?event :window.event;
}

调用的时候

btn.onclick=function(event){
    event=EventUtil.getEvent(event);//这行代码添加到开头,确保随时可以使用event对象,不必担心用户使用的什么浏览器
};

2、获取目标元素

getTarget:function(){
    return event.target || event.srcElement;
},

调用

btn.onclick=function(event){
    event=EventUtil.getEvent(event);
    var target=Event.getTarget(event);
};

3、取消事件默认行为

preventDefault:function(event){
    if(event.preventDefault){
        event.preventDefault();
    }else{
        event.returnValue=false;
    }
}

调用

var link=document.getElementById("myLink");
link.onclick=function(event){
    event=EventUtil.getEvent();
    EventUtil.preventDefault(event);
}

4、阻止事件冒泡

stopPropagation:function(event){
    if(event.stopPropagation){
        event.stopPropagation();
    }else{
        event.cancelBubble=true;
    }
}

调用

var link=document.getElementById("myLink");
link.onclick=function(event){
    event=EventUtil.getEvent();
    EventUtil.stopPropagation(event);
}

document.body.onclick=function(event){
    alert("Body clicked");
}

三、获得相关元素

getRelatedTarget:function(event){
    if(event.relatedTarget){
        return event.relatedTarget;
    }else if(event.toElement){
        return event.toElement;
    }else if(event.fromEvent){
        return event.fromEvent;
    }else{
        return null;
    }
}

四、 获得鼠标按钮

对于mousedown和mouseup事件,在event对象中存在一个button属性,表示按下或释放的按钮。

DOM的button属性有3个取值:

  • 0:表示主鼠标按钮(鼠标左键)
  • 1:表示中间的鼠标按钮(鼠标滚轮按钮)
  • 2:表示次鼠标按钮(鼠标右键)

 IE8及之前版本也提供了button属性,但这个属性的值与DOM的button属性有很大差异。

  • 0:表示没有按按钮。——》0
  • 1:表示按下了鼠标左键——》0
  • 2:表示按下了鼠标右键——》2
  • 3:表示同时按下了鼠标左右键——》0
  • 4:表示按下了中间的鼠标按钮——》1
  • 5:表示同时按下了鼠标左键和中间的鼠标按钮——》0
  • 6:表示同时按下了鼠标右键和中间的鼠标按钮——》2
  • 7:表示同时按下了三个鼠标按钮——》》DOM0

兼容性处理:将IE中其他选项分别转换成如同按下这三个按键中的一个即可(同时将主按钮作为优先选取的对象)。IE中返回的5和7会被转换成DOM模型中的0。由于两种模型有同名的button属性,所以不能直接用能力检测。支持DOM版鼠标事件的浏览器可以通过hasFeature()方法来检测,所以跨浏览器的getButton()方法如下:

getButton:function(event){
    if(document.implementation.hasFeature("MouseEvents","2.0")){
        return event.button;
    }else{
        switch(event.buton){
            case 0:
            case 1:
            case 3:
            case 5:
            case 7:
                    return 0;
            case 2:
            case 6:
                    return 2;
            case 4:
                    return 1;                                                
        }
    }        

}

调用:

var div=document.getElementById("myDiv");
EventUtil.addHandler(div,"mouseout",function(event){
    event=EventUtil.getEvent(event);
    alert(EventUtil.getButton(event));
});

五、获取鼠标滚动增量值

DOM中当用户向前滚动鼠标滚轮时,wheelDelta是120的倍数;当用户向后滚动鼠标滚轮时,wheelDelta是-120的倍数。

Opera 9.5之前的版本,wheelDelta值的正负号是颠倒的。

Firefox支持一个DOMMouseScroll的类似事件,且鼠标有关信息保存在detail属性中。当向前滚动鼠标滚轮时,这个属性的值是-3的倍数,向后滚动鼠标滚轮时,这个值是3的倍数。

getWheelDelta:function(event){
    if(event.wheelDelta){
        return(client.engine.opera && client.engine.opera<9.5? -event.wheelDelta:event.wheelDelta);
    }else{
        return -event.detail*40; 
    }
}

调用:

可以将相同的事件处理程序指定给mousewheel和DOMMouseScroll事件了。

(function(){
    function handleMouseWheel(event){
        event=EventUtil.getEvent(event);
        var delta=EventUtil.getWheelDelta(event);
        alert(delta);
    }
    EventUtil.addHandler(document,"mousewheel",handleMouseWheel);
    EventUtil.addHandler(document,"DOMMouseScroll",handleMouseWheel);
})();

如果没有封装的话,client.engine.opera 这句代码运行下会报错client is not defined,因为目前还没有封装这个方法,所以等下一个博客我会研究代理检测封装下这个方法; 所以先不考虑opera9.5,先注释掉这句代码;

六、获取字符编码

IE9,Firefox,Chrome和Safari的event对象的charCode 属性代表按下那个键所代表字符的ASCII编码。

IE8及之前版本中Opera是在keyCode中保存字符的ASCII编码。

检查charCode属性是否可用,不可用则使用keyCode。

getCharCode:function(event){
    if(typeof event.charCode=="number"){//在不支持的浏览器中值是undefined
        return event.charCode;
    }else{
        return event.keyCode;
    }
}

调用

EventUtil.addHandler(textbox,"keypress",function(event){
    event=EventUtil.getEvent(event);
    console.log(EventUtil.getCharCode(event));
});  

 

本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:http://www.cnblogs.com/starof/p/6555142.html有问题欢迎与我讨论,共同进步。

posted @ 2017-04-27 11:03  starof  阅读(582)  评论(0编辑  收藏  举报