目前使用的3中完全不同的不兼容的事件处理模型:
1.原始事件模型:通常非正式把它看作0级DOM API的一部分内容。尽管它的特性有限,但所有启用Javascript的浏览器都支持它,因此具有可移植性。
2.标准事件模型:2级DOM标准对它进行了标准化,除IE外的所有浏览器都支持他。
3.Internet Explorer事件模型:最初由IE4引入。具有标准事件模型的许多高级特性,但不具有全部特性。
把一个元素设置为多个文档元素的事件句柄:
//在链接前请求用户的确认 function confirmLink() { return confirm("您确认要访问“ + this.href + ” 吗?"); } function confirmAllLinks() { for(var i = 0; i < document.links.length; i++) { document.links[i].onclick = confirmLink; } }
假定对象o,具有mymethod方法,可以用下面代码注册一个事件句柄
button.onclick = o.mymethod
这个语句使button.onclick引用与o.mymethod相同的函数。现在这个函数既是o的方法,也是button的方法。当浏览器触发这个事件句柄时,它将把该函数作为button对象的方法调用,而不是作为o对象的方法调用。关键字this引用Button对象,而不是引用对象o。不要认为可以让浏览器把一个事件句柄作为其他对象的方法调用。如果想这样做,必须直接调用
button.onclick = function() { o.mymethod(); }
?
?
?
列表显示了所有事件模块、以及它定义的事件接口和它支持的事件类型。
模块名 |
事件接口 |
事件类型 |
HTMLEvents |
Event |
abort 、 blur 、 change 、 erro 、 focus 、 load 、 resrt 、 resize 、 scroll 、 select 、 submit 、 unload |
MouseEvents |
MouseEvents |
click 、 mousedown 、 mousemove 、 mouseover 、 mouseup |
UIEvents |
UIEvent |
DOMActivate 、 DOMFocusln 、 DOMFocusOut |
Event : HTMLEvent 模块定义的事件类型使用 Event 接口。其他事件类型都使用该接口,即所有事件对象都实现了 Event 接口,并提供了适用于所有事件类型的详细信息。 Event 接口定义了如下属性:
type |
发生事件的类型。该属性的值是事件类型名(如: ’click’ 、 ’mouseover’ ) |
target |
发生事件的节点,可能与 currentTarget 不同 |
currentTarget |
当前正在运行事件句柄的节点。如果在传播过程的捕捉阶段或起泡阶段处理事件,这个属性的值就与 target 属性的值不同。 |
eventPhase |
一个数字,指定当前所处的事件传播过程的阶段。它的值为常量: Event.CAPTURE_PHASE, Event_AT_TARGET, Event.BUBBLING_PHASE |
timestamp |
一个 Date 对象,声明事件何时发生 |
bubble |
布尔值,声明该事件是否在文档树中起泡 |
cancelabel |
布尔值,声明该事件是否具有能用 preventDefault() 方法取消的默认动作 |
Event 接口还定义了 stopPropagation() 和 preventDefault() 方法,所有事件对象都实现了它们。调用 stopPropagation() 方法可以阻止事件从当前正在处理它的节点传播。调用 preventDefault() 方法阻止浏览器执行与该事件默认的相关动作。
?
UIEvent : UIEvent 接口是 Event 的子接口(拥有 Event 接口定义的属性)、是 MouseEvent 接口的父接口。
view 属性:发生时间的 Window 对象
detail 属性:对于 click 事件、 mousedown 事件和 mouseup 事件,这个字段代表点击的次数, 1 代表点击一次、 2 代表双击、 3 代表点击三次。对于 DOMActivate 事件,这个字段的值为 1 ,表示正常激活, 2 表示超级激活(如双击鼠标或同时按下 shift 和 enter )
?
MouseEvent :继承 Event 接口和 UIEvent 接口的所有属性和方法,此外还定义了如下属性
button |
声明在 mousedown 、 mouseup 、 click 事件中,哪个鼠标键改变了状态。 0 表示左键, 1 表示中间键, 2 表示右键。 |
altKey,ctrlKey,metaKey,shiftKey |
这 4 个布尔值声明在鼠标事件发生时,是否按住了 alt 键, ctrl , shift , meta 。 |
clientX,clientY |
声明鼠标指针相对于客户区或浏览器窗口的 X 坐标和 Y 坐标。这 2 个属性不考虑滚动,如果事件发生在窗口的顶部,无论文档滚动了多元, clientY 都是 0 |
screenX, screenY |
声明鼠标指针相对于用户显示器的左上角的 X 坐标和 Y 坐标 |
relatedTarget |
对于 mouseover 事件,它是鼠标移到目标上是所离开的那个节点 对于 mouseout 事件,它是离开目标时,鼠标进入的节点 |
?
?
在0级DOM事件模型中。浏览器把事件分派给发生事件的文档元素。如果那个对象具有合适的事件句柄。就运行这个句柄。除此之外,不再执行其他的操作。
在2级DOM中,当事件发生在文档元素上时,目标的事件句柄就被触发。此外,目标的每个祖先元素也有机会处理那个事件。
事件捕获分三个阶段进行:
1.在捕捉(caputuring)阶段,事件从Document对象沿着文档树向下传播给目标节点。如果目标的任何一个祖先专门注册了捕捉事件句柄,那么在事件传播的过程中,就会运行这些句柄。
2.直接注册在目标上的适合的事件句柄将运行。
3.起泡(bubbling)阶段:事件将从目标元素向上传播回或起泡回Document对象的文档层次。(虽然所有事件都受时间传播的捕捉阶段的支配,但并非所有类型的事件都起泡)
在2级事件模型中,可调用对象的addEventListener()方法为特定元素注册事件句柄
document.myform.addEventListener("submit", function(e) { alert(e);}, false);
addEventListener函数对应的是removeEventListener
IE事件句柄的注册:attachEvent()方法和detachEvent()
function highlight() { /* code goes here*/} document.getElementById('myelt').attachEvent("onmouseover", highlight);
attachEvent()和addEventListener()方法相似,除以下几点外:
1.只是由于IE事件不支持事件捕捉。因此attachEvent()方法只有2个参数
2.传递给IE方法的事件句柄名字应该包含一个“on”前缀
3.用attachEvent()注册的函数将被作为全局函数调用,即在attachEvent()注册的事件句柄执行时,关键字this引用的是Window对象,而不是事件的目标元素
4.attachEvent()允许同一个事件句柄注册多次。
IE中的事件起泡:IE事件模型中没有2级DOM模型具有的事件捕捉的概念。但在IE模型中,事件可以沿着包容层次向上起泡。在2级模型中,事件起泡只适用于原始事件或输入事件(主要是鼠标和键盘事件),不适用于高级的语义事件。IE中的事件起泡和2级DOM事件模型中的事件起泡之间的差别在于停止起泡的方式。IE Event对象没有DOM Event对象具有的stopPropagation()方法,所以要阻止事件起泡或制止它在包含层次中进一步传播,IE事件句柄必须把Event对象的cancelBubble属性设置为true:
window.event.cancelBubble = true;
设置cancelBubble属性只使用于当前事件。当新事件生成时,将赋予window.event新的Event对象,cancelBubble属性还将还原为它的默认值false
?
下面代码为拖动决定定位的元素:
<script type="text/javascript"> //拖动绝对定位的元素 function drag(elementToDrag, event) { var startX = event.clientX, startY = event.clientY; var origX = elementToDrag.offsetLeft, origY = elementToDrag.offsetTop; var deltaX = startX - origX, deltaY = startY - origY; if (document.addEventListener) { document.addEventListener("mouseover", moveHandler, true); document.addEventListener("mouseup", upHandler, true); } else if (document.attachEvent) { //IE5+事件模型 elementToDrag.setCapture(); elementToDrag.attachEvent("onmousemove", moveHandler); elementToDrag.attachEvent("onmouseup", upHandler); elementToDarg.attachEvent("onlosecapture", upHandler); } else { //IE4事件模型 var oldmovehandler = document.onmousemove; var olduphandler = document.onmouseup; document.onmousemove = moveHandler; document.onmouseup = upHandler; } if (event.stopPropagation) event.stopPropagation(); else event.cancelBubble = true; //阻止默认动作 if (event.preventDefault) event.preventDefault(); else event.returnValue = false; function moveHandler(e) { if (!e) e = window.event; elementToDrag.style.left = (e.clientX - deltaX) + "px"; elementToDrag.style.top = (e.clientY - deltaY) + "px"; if (e.stopPropagation) e.stopPropagation(); else e.cancelBubble = true; } function upHandler(e) { if (!e) e = window.event; if (document.removeEventListener) { //DOM事件模型 document.removeEventListener('mouseup', upHandler, true); document.removeEventListener("mousemove", moveHandler, true); } else if (document.detachEvent) { //IE5+事件模型 elementToDrag.detachEvent("onlosecapture", upHandler); elementToDrag.detachEvent("onmouseup", upHandler); elementToDrag.detachEvent("onmousemove", moveHandler); elementToDrag.releaseCapture(); } else { //IE4事件模型 document.onmouseup = oldhandler; document.onmousemove = oldmoveHandler; } if (e.stopPropagation) e.stopPropagation(); else e.cancelBubble = true; } } </script> </head> <body> <div style="position:absolute; left:100px; top:100px; width:250px; background-color:white; border:solid black;"> <div style="background-color:gray; border-bottom:dotted black; padding:3px; font-family:sans-serif; font-weight:bold;" onmousedown="drag(this.parentNode, event);"> 拖动我</div> <p>测试段落</p><p>测试段落</p><p>测试段落</p><p>测试段落</p> </div>
?
?
?
按键事件:如果 alt,ctrl,shift 和一个按键一起按下,这通过事件对象的 altKey,ctrlKey,shiftKey 属性来表示。
在 Firefox 中定义了两个属性, keyCode 存储了一个按键的较低层次的虚拟键盘码,并且和 keydown 事件一起发送; charCode 存储了按下一个键时所产生的可打印的字符的编码,并且和 keypress 事件一起发送(功能按键产生一个 keypress 事件,此时 charCode 为 0 , keyCode 包含了虚拟按键码)。
在 IE 中,只有一个 keyCode 属性,并且它的解释也取决于事件的类型,对于 keydown 事件来说, keyCode 是一个虚拟按键码;对于 keypress 事件来说, keyCode 是一个字符码。字符码可以使用 String.fromCharCode() 转换为字符。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>限制用户输入某一组字符</title> </head> <body> 邮编:<input type="text" id="zip" allowed="0123456789" messageid="zipwarn"> <span id="zipwarn" style="color:red; visibility:hidden">只能输入数字<span> </body> <script type="text/javascript"> (function check() { //文档加在完毕后,执行init函数 if (window.addEventListener) window.addEventListener('load', init, false); else if(window.attachEvent) window.attachEvent("onload", init); //查找input元素,并在其上注册init函数 function init() { var inputtags = document.getElementsByTagName("input"); for(var i = 0; i < inputtags.length; i++) { var tag = inputtags[i]; if (tag.type != "text") continue;//仅需要text框 var allowed = tag.getAttribute("allowed"); if (!allowed) continue;//有allowed属性 if (tag.addEventListener) tag.addEventListener("keypress", filter, false); else { //此处不用attacheEvent tag.onkeypress = filter; } } } //处理用户输入 function filter(event) { //获取事件模型和字符码 var e = event || window.event; var code = e.charCode || e.keyCode; if (e.charCode == 0) return true; if (e.ctrlKey || e.altKey) return true; if (code < 32) return true; var allowed = this.getAttribute("allowed"); var messageElement = null; var messageid = this.getAttribute("messageid"); if (messageid) messageElement = document.getElementById(messageid); var c = String.fromCharCode(code); if (allowed.indexOf(c) != -1) { if (messageElement) messageElement.style.visibility = 'hidden'; return true; } else { if (messageElement) messageElement.style.visibility = "visible"; if (e.preventDefault) e.preventDefault(); if (e.returnValue) e.returnValue = false; return false; } } })(); </script> </html>?
鼠标事件:当一个鼠标事件发生的时候,事件对象的clientX和clientY属性保存了鼠标指针的位置。
onload事件:有些javascript代码要修改包含它们的文档,通常这样的代码必须要在文档完全加载完毕后才能运行。
?