让Firefox支持event对象实现代码

通常为了兼容IE与FireFox,一般的事件处理方法为:


代码如下:

btn.onclick=handle_btn_click;
function handle_btn_click(evt){
if(evt==null)evt=window.event;//IE
//处理事件.
}

对于简单的程序,这不算麻烦.
但对于一些复杂的程序,某写函数根本就不是直接与事件挂钩的.如果要把event传进该参数,那么所有的方法都要把event传来传去..这简直就是噩梦.
下面介绍一个解决这个麻烦事的方法,与原理.
JScript中,函数的调用是有一个 func.caller 这个属性的.
例如


代码如下:

function A()
{
B();
}
function B()
{
alert(B.caller);
}

如果B被A调用,那么B.caller就是A
另外,函数有一个arguments属性. 这个属性可以遍历函数当前执行的参数:


代码如下:

function myalert()
{
var arr=[];
for(var i=0;i<myalert.arguments.length;i++)
arr[i]=myalert.arguments[i];
alert(arr.join("-"));
}
myalert("hello","world",1,2,3)

就能显示 hello-world-1-2-3
(arguments的个数与调用方有关,而与函数的参数定义没有任何关系)
根据这两个属性,我们可以得到第一个函数的event对象:


代码如下:

btn.onclick=handle_click;
function handle_click()
{
showcontent();
}
function showcontent()
{
var evt=SearchEvent();
if(evt&&evt.shiftKey)//如果是基于事件的调用,并且shift被按下
window.open(global_helpurl);
else
location.href=global_helpurl;
}
function SearchEvent()
{
func=SearchEvent.caller;
while(func!=null)
{
var arg0=func.arguments[0];
if(arg0)
{
if(arg0.constructor==Event) // 如果就是event 对象
return arg0;
}
func=func.caller;
}
return null;
}

这个例子使用了SearchEvent来搜索event对象. 其中 'Event' 是 FireFox 的 event.constructor .
在该例子运行时,
SearchEvent.caller就是showcontent,但是showcontent.arguments[0]是空.所以 func=func.caller 时,func变为handle_click .
handle_click 被 FireFox 调用, 虽然没有定义参数,但是被调用时,第一个参数就是event,所以handle_click.arguments[0]就是event !
针对上面的知识,我们可以结合 prototype.__defineGetter__ 来实现 window.event 在 FireFox 下的实现:
下面给出一个简单的代码.. 有兴趣的可以补充(本人已经有修改)


代码如下:

<script language="javascript">
function handle_click() {
if(window.addEventListener)
{
FixPrototypeForGecko();
alert(window.event.srcElement)
}
}
function FixPrototypeForGecko()
{
HTMLElement.prototype.__defineGetter__("runtimeStyle",element_prototype_get_runtimeStyle);
window.constructor.prototype.__defineGetter__("event",window_prototype_get_event);
Event.prototype.__defineGetter__("srcElement",event_prototype_get_srcElement);
}
function element_prototype_get_runtimeStyle()
{
//return style instead...
return this.style;
}
function window_prototype_get_event()
{
return SearchEvent();
}
function event_prototype_get_srcElement()
{
return this.target;
}
function SearchEvent()
{
//IE
if(document.all)
return window.event;
func=SearchEvent.caller;
while(func!=null)
{
var arg0=func.arguments[0];
if(arg0)
{
//if(arg0.constructor==Event)
if(arg0.constructor==Event||arg0.constructor==MouseEvent || (typeof(arg0)=="object" && arg0.preventDefault && arg0.stopPropagation))
return arg0;
}
func=func.caller;
}
return null;
}
</script>
<div id="mydiv" onclick="handle_click();">click here!!</div>

javascript和JScript也是不相同的,前者是客户端的脚本,后者是服务端的脚本和VBScript一样被服务端所支持
当然我这里不是要说两者的区别,只是让自己了解到自己现在的水平(不是一般的差)...
如果就只给出了上面的代码,相信刚开始要搞兼容性的朋友一定很难看理解这些代码的用处
这里我就一一的解释下上面这些代码的用法吧
先看下__defineGetter__和__defineSetter__这两个方法的解释吧:
一.Getter是一种获取一个属性的值的方法,Setter是一种设置一个属性的值的方法。可以为任何预定义的核心对象或用户自定义对象定getter和setter方法,从而为现有的对象添加新的属性。
二.可以在什么时候对对象和事件添加新的属性?
1.在对象初始化时定义
2.在对象定义后通过Object的__defineGetter__、__defineSetter__方法来追加定义
详细的用法可以在请看这里对__defineGetter__、__defineSetter__的解释(地址:http://anbutu.javaeye.com/blog/post/194276)
所以我们看到了,在FixPrototypeForGecko()函数里分别给三个对象添加了属性,当然是在FF下对对象的添加:
HTMLElement添加了"runtimeStyle"属性,属性值为element_prototype_get_runtimeStyle函数的返回的值
window添加了"event"属性,属性值为window_prototype_get_event返回的值
Event添加了"srcElement"属性,基属性值为event_prototype_get_srcElement函数所返回的值
这样我们就为这三个对象在FF下扩展了新的属性
所以我们在判断浏览器是否为FF后执行FixPrototypeForGecko()过程,这个时候在FF下这三个对象的就有了新的属性
于是当我们点击DIV标签后在弹出的窗口中我们看到了"[object HTMLDivElement]"字样,也说明我们已经成功的为window对象添加了event属性


代码如下:

if(window.addEventListener) {
FixPrototypeForGecko();
alert(window.event.srcElement)
}

大家可以看到element_prototype_get_runtimeStyle过程和event_prototype_get_srcElement过程所以返回的值都能很容易理解
那下面我们来看看window_prototype_get_event()过程是怎么样返回事件的
过程的返回值是SearchEvent()过程的结果,看下这个过程


代码如下:

function SearchEvent()
{
//IE
if(document.all)
return window.event;
func=SearchEvent.caller;
while(func!=null)
{
var arg0=func.arguments[0];
if(arg0)
{
//if(arg0.constructor==Event||arg0.constructor==MouseEvent)
if(arg0.constructor==Event||arg0.constructor==MouseEvent || (typeof(arg0)=="object" && arg0.preventDefault && arg0.stopPropagation))
return arg0;
}
func=func.caller;
}
return null;
}

要明白这个过程就得先明白两个方法:caller和arguments(在文章上面有相应的解释)
在这里再解释下constructor构造者这个属性,返回的是对象的相应对象的创建者
在while循环里alert(func)我们就可以看到func.caller的返回了,最后一次返回的就是我们的鼠标点击事件了
因为handle_click()过程是我们在点击div后执行的,所以最后的func.caller就是我们的点击事件了,这个时候的funcj就是 handle_click(),那么也就相当于是handle_click.caller,当然handle_click的调用者当然就是onclick 事件了,也就是[MouseEvent]
可以看到我在 if(arg0.constructor==Event||arg0.constructor==MouseEvent)增加了一个条件,是因为arg0.constructor现在的结果就是MouseEvent
看到这里相信大家也知道在FF下怎样编写event了
最后再说下"addEventListener"为对象注册事件方法


代码如下:

<script>
function addObjectEvent(objId,eventName,eventFunc)
{
var targetObj = document.getElementById(objId);
if(targetObj)
{
if(targetObj.attachEvent)
{
targetObj.attachEvent(eventName,eventFunc);
}
else if(targetObj.addEventListener)
{
eventName = eventName.toString().replace(/on(.*)/i,'$1');
targetObj.addEventListener(eventName,eventFunc,true);
}
}
}
function test1()
{
alert('test1');
}
function test2()
{
alert('test2');
}
</script>
<div id="hi" onclick="MyTest();">on click</div>
<script>
addObjectEvent('hi','onclick',test1);
addObjectEvent('hi','onclick',test2);//先执行test2(队列)
</script>

(0)

相关推荐

  • 让Firefox支持event对象实现代码

    通常为了兼容IE与FireFox,一般的事件处理方法为: 复制代码 代码如下: btn.onclick=handle_btn_click; function handle_btn_click(evt){ if(evt==null)evt=window.event;//IE //处理事件. } 对于简单的程序,这不算麻烦. 但对于一些复杂的程序,某写函数根本就不是直接与事件挂钩的.如果要把event传进该参数,那么所有的方法都要把event传来传去..这简直就是噩梦. 下面介绍一个解决这个麻烦事的

  • 让FireFox支持innerText的实现代码

    为firefox实现innerText属性很多代码写了又忘忘了又写,很浪费,所以决定养成做笔记的习惯. 知识点: 0.为什么要innerText?因为安全问题 1.为firefox dom模型扩展属性 2.currentStyle属性可以取得实际的style状态 3.IE实现innerText时考虑了display方式,如果是block则加换行 4.为什么不用textContent?因为textContent没有考虑元素的display方式,所以不完全与IE兼容 复制代码 代码如下: <html

  • FireFox JavaScript全局Event对象

    而在FireFox中却没有这样的对象,如果有函数嵌套调用,需要不停的向下传递Event,例如下面的场景. 复制代码 代码如下: <div style="background-color:Red; width:300px; height:300px;" onclick="Test(event,this);" id="panel"></div> function Test(event,dom){ Test1(event); }

  • JavaScript event对象整理及详细介绍

    Event属性和方法: 1. type:事件的类型,如onlick中的click: 2. srcElement/target:事件源,就是发生事件的元素: 3. button:声明被按下的鼠标键,整数,1代表左键,2代表右键,4代表中键,如果按下多个键,酒把这些值加起来,所以3就代表左右键同时按下:(firefox中 0代表左键,1代表中间键,2代表右键) 4. clientX/clientY:事件发生的时候,鼠标相对于浏览器窗口可视文档区域的左上角的位置:(在DOM标准中,这两个属性值都不考虑

  • JavaScript  event对象整理及详细介绍

    Event属性和方法: 1. type:事件的类型,如onlick中的click: 2. srcElement/target:事件源,就是发生事件的元素: 3. button:声明被按下的鼠标键,整数,1代表左键,2代表右键,4代表中键,如果按下多个键,酒把这些值加起来,所以3就代表左右键同时按下:(firefox中 0代表左键,1代表中间键,2代表右键) 4. clientX/clientY:事件发生的时候,鼠标相对于浏览器窗口可视文档区域的左上角的位置:(在DOM标准中,这两个属性值都不考虑

  • event对象获取方法总结在google浏览器下测试

    简介: Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 事件通常与函数结合使用,函数不会在事件发生前被执行! Event对象的获取方法: 方法一: 例如: 复制代码 代码如下: function demo1(e){ var e = e || window.event; //此种方法在ie中和google中可以不传参数e也可以获取到event,但是在火狐中必须在事件方法中传递event参数 //才可以获取到event对象. } <input

  • IE和Firefox下event事件杂谈

    因为javascript的事件模型有三种,它们分别是NN4.IE4+和W3C/Safari;这也造成了在不同的浏览器中处理event的差异,这里结合一些零碎的代码来说明如何做到event在IE4+和Firefox下的正常工作.首先看如下代码: 复制代码 代码如下: function doEventThing(eventTag){ var event = eventTag||window.event; var currentKey = event.charCode||event.keyCode;

  • 用javascript获取当页面上鼠标光标位置和触发事件的对象的代码

    用javascript获取鼠标位置: 复制代码 代码如下: function mousePosition(ev) { if (ev.pageX || ev.pageY) { return { x: ev.pageX, y: ev.pageY }; } return { x: ev.clientX + document.body.scrollLeft - document.body.clientLeft, y: ev.clientY + document.body.scrollTop - docu

  • html的DOM中Event对象onblur事件用法实例

    本文实例讲述了html的DOM中Event对象onblur事件用法.分享给大家供大家参考.具体分析如下: onblur 事件会在对象失去焦点时发生. 语法如下: 复制代码 代码如下: onblur="SomeJavaScriptCode" SomeJavaScriptCode 必需.规定该事件发生时执行的 JavaScript. 支持该事件的 HTML 标签: <a>, <acronym>, <address>, <area>, <

  • 解决jquery1.9不支持browser对象的问题

    最近因项目需要,要用jquery的cycle插件,但是项目里面一直用的都是jquery1.9,不支持browser对象,百度一下,找到了解决方案. 在cycle插件的源码里面直接加上下面这段代码就可以了: 复制代码 代码如下: (function(jQuery){ if(jQuery.browser) return; jQuery.browser = {}; jQuery.browser.mozilla = false; jQuery.browser.webkit = false; jQuery

随机推荐