当前位置: 代码迷 >> JavaScript >> 札记:JS权威指南17章―事件和事件属性
  详细解决方案

札记:JS权威指南17章―事件和事件属性

热度:466   发布时间:2012-10-26 10:30:59.0
笔记:JS权威指南17章―事件和事件属性

目前使用的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代码要修改包含它们的文档,通常这样的代码必须要在文档完全加载完毕后才能运行。

?

  相关解决方案