事件流
冒泡型事件(IE上的解决方案)
事件按照从最特定的事件目标到最不特定的事件目标的顺序触发.(而且IE6.0使<html/>元素也可接收冒泡的事件,最顶层为document事件)
如果不确定用户用的是IE5.5还是IE6,最好避免在<html/>元素级别上处理事件
<html onclick="handleClick()">
<head>
<title>Example</title>
</head>
<body onclick="handleClick()">
<div onclick="handleClick()"> Click Me! </div>
</body>
</html>
四个流程:div,body,html,document的onclick事件
Mozilla 1.0及更高版本也支持冒泡型事件,但达到了另一层次.它也支持<html/>元素级别的事件,但,事件"起泡"一直上升到windows窗口对象(并不是DOM标准的一部分)
如上面的例子有五个流程:div,body,html,document,window的onclick事件
捕获型事件(Netscape Navigator4.0)
与冒泡刚好相反的过程:从最不精确的对象(document对象)开始触发,然后到最精确(可以在窗口级别捕获事件,不过必须开发人员特别指定).
Netscape Navigator不会把页面上的很多元素暴露给事件
再如上面的例子:两个流程:document,div的onclick事件
DOM事件流
DOM同时支持上面两种事件模型.但是捕获型事件先发生.两种事件流会触及DOM中的所有对象.从document开始,在也document结束.(大部分兼容标准的浏览器会继续将事件的捕获/冒泡延续到window对象)
但DOM中,文本节点也触发事件(在IE中不会),如果点击文本 Click Me! ,实际的事件流应该如下:
五个流程:window,document,body,div,text,text,div,body,document,window的onclick事件
事件处理函数/监听函数
事件这种特定行为都有自己的名字,如click,load,mousover,用于响应某个事件而调用的函数称为事件处理函数,或DOM称之为事件监听函数.
事件处理函数的两种分区方式(JavaScript,HTML):
var div = document.getElementById("div1");
div.onclick = function(){
alert("hello");
};
这种方法事件处理的函数名必须小写才能正确响应
<div onclick = "alert('hello')"></div> // 不区分大小写
这两种方法在所有流行的浏览器中都可以使用.
但传统的做法还能为每个可用事件分配多个事件处理函数.但IE和DOM包含的方法名称却不同
IE:
在IE中,每个元素和window对象都有两个方法: attachEvent()和detachEvent()
参数:要分配的事件处理函数的名字 (onclick)和函数
attachEvent("name_of_event_handler",fnHandler); 给一个事件附加事件处理函数
detachEvent("name_of_event_handler",fnHandler); 将事件处理函数分离出来
如:
var fnClick = function(){alert("click");};
var div = document.getElementById("div1");
div.attachEvent("onclick",fnClick); //add
div.detachEvent("onclick",fnClick); //remove
它还可与前面的方法合用:
div.onclick = fnClick; // 最好放最前
div.attachEvent("onclick",******);
可以添加多个处理函数:
div.attachEVent(("onclick",fnClick1);
div.attachEVent(("onclick",fnClick2);
DOM:
addEventListener()和removeEventListener()分别用例分配和移除事件处理函数
参数:1.事件名称 2.分配函数 3 .处理函数是用于冒泡阶段(false)还是捕获阶段(true)
1.addEventListener("name_of_event",fnHandler,bCapture);
2.removeEventListener("name_of_event",fnHandler,bCapture);
如: div.addEventListener("click",fnClick,false); // 有效! DOM中click IE 用onclick
1)如果使用addEventListener()将事件处理函数加入捕获阶段 则必须在removeEventListener()
中指明捕获阶段,才能正确的将这个事件处理函数删除.
例子:
var fnClick = function(){alert("click");};
var div = document.getElementById("div1");
div.addEventListener("click",fnClick,false);//添加到冒泡阶段
div.removeEventListener("click",fnClick,true);//在捕获阶段删除
虽不会产生错误,但不会删除
2)如果使用传统方法直接给事件处理函数属性赋值 ,事件处理函数将添加到事件冒泡阶段
oDiv.onclick=fnClick;
div.addEventListener("click",fnClick,false); //效果一样
3)直接赋时 后续对事件处理函数的赋值清除前面的赋值
oDiv.onclick=fnClick;
oDiv.onclick=fnDifferentClick;
事件对象
事件发生时会创建事件对象,它包含如下刚刚发生的事件的信息:
1.引起事件的对象
2.事件发生的鼠标的信息
3.事件发生时键盘的信息
事件对象只在发生事件时才被创建,且只有事件处理函数才能访问.所有事件处理函数执行完毕后,事件对象就被销毁.
定位
IE中,事件对象是 window 对象的一个属性 event.事件处理函数必须如下访问事件对象:
div.onclick = function(){
var event = window.event; // 只能这么访问,处理完后销毁
}
DOM 标准中, event 对象必须作为唯一的参数传给事件处理函数.所以,在DOM兼容的浏览器中访问事件对象要如下做:
div.onclick = function(){
var event = arguments[0];
}
或
div.onclick = function(event){
var happenedevent = event;
}
IE和DOM通用
1.获取事件类型
1)可以在任何一种浏览器中获取事件的类型: var eventType = event.type;
如:click mouseover 等
2)当某个函数同时为两个事件的处理函数时,这会很有用.(注意两者获得事件对象的方式不同)
var click1 = function(event){ alert(event.type);}; // 对支持DOM的浏览器
var click1 = function(){ var event = window.event; alert(event.type);}; // IE中代码
2.获取按键代码(keydown/keyup事件)
在keydown/keyup事件中,可以使用keyCode属性来获取按下的键的数值代码:
var keyCode = event.keyCode; ( Enter :13 space :32)
3.检测Shift,Alt,Ctrl键:
var shift = event.shiftKey; var alt = event.altKey; var ctrl = event.ctrlKey;
4.获取客户端坐标:
var clientX = event.clientX; var clientY = event.clientY; // 鼠标离网页的窗口边界有多远
// 注意:可能是离最近的边界的两个值.书上的标识是离上边界和右边界的位置
5.获取屏幕坐标:
var screenX = event.screenX; var screenY = event.screenY; // 也没有指明是哪些边界!
区别:
1.获取目标
位于事件中心的对象称为目标target.假如<div/>元素分配onclick事件处理函数触法click事件时,<div/>就被认为是目标
在IE中,目标包含在event对象的srcElement属性中
var oTarget=oEvent.srcElement;
在DOM兼容的浏览器中,目标包含在target属性中
var oTarget=oEvent.target;
2.获取字符代码
IE 和DOM都支持event对象的keyCode属性 ,它会返回按键的数值代码,如果按键代表一个字符(非Shift Ctrl Alt等), IE的keyCode将返回字符的代码(等于它的Unicode值)
在DOM中,按键的代码和字符会 有一个分离.要获取字符代码,用charCode属性: var icharcode=oEVent.charCode; 然后可用这个值获取实际的字符.用String.fromCharCode()方法
var sChar=String.fromCharCode(oEvent.);如果不确定按下的是否是字符,可用isChar属性进行判断 if(oEvent.isChar){var icharcode=oEVent.charCode;}
3.阻止某个事件的默认行为
IE中: oEvent.returnValue=false;
Mozilla中: oEvent.preventDefault();
一般性将对不同浏览器的事件处理函数放在一起的方法:
document.body.oncontextmenu = function(oEvent){ // 阻止contextmenu事件的默认行为(在页面上右键鼠标跳出的菜单)
if(isIE){
event = window.event;
event.returnValue = false;
}
else{
event.preventDefault();
}
};
4.停止事件复制(进一步的冒泡)
IE: 设置cancelBubble属性为true: event.cancelBubble = true;
Mozilla: 只需调用stopPropagation()方法 event.stopPropagation();
这可以防止因为一个元素触发了事件,而使也触发它的父元素,document等的事件也触发
事件的类型
对于鼠标事件,每个鼠标事件都会给以下event对象的属性填入值:
坐标属性
type属性
target(DOM)或srcElement(IE)属性
shiftKey,ctrlKey,altKey,metaKey(DOM)属性
button属性(只在mousedown,mouseover,mouseout,mousemove,mouseup事件中)
鼠标事件是 web 上最常用的事件类型.其中包含以下事件: (都包含上面的属性)
click 点右键或焦点在些元素上而且按了回车
dblclick 双击左键
mousedown 用户点击任意一个鼠标按钮时发生
mouseout 在某个元素,且正要将其移出 (IE中还含fromElement,toElement,DOM中relatedTarget)
mouseover 移出一个元素,到另一个元素上 (IE中还含fromElement,toElement,DOM中relatedTarget)
mouseup 用户松开任意一个按钮时发生
mousemove 鼠标在某个元素上持续发生
<img src="a.gif" onmouseover="this.src='b.gif'" onmouseout="this.src='a.gif'" />
值得注意的是Opera 7.5在检测不同的按键(Shift,Ctrl和Alt)时有Bug.它错误地把shift键报告为ctrl键,且不会检测Alt键
顺序:
如要发生dbclick事件,在同一个目标上要按顺序发生: mousedown mouseup click; mousedown mouseup click dbclick
移动鼠标从一个对象进入另一个对象时,先发生的事件是mouseout.然后在这两个对象上都触发mousemove事件,最后在进入的那个对象上触发mouseover事件
键盘事件
keydown 按下某键盘键时发生,一直按着不断触发(Opera除外)
keypress 按下一个字符键(非shift等键),一直按着,会持续发生
keyup 释放按键时发生
每个键盘事件都会填入的事件属性
keyCode属性
charCode属性(仅DOM)
target(DOM)或srcElement(IE)属性
shiftKey,ctrlKey,altKey,metaKey(DOM)属性
function handleEvent(event){
if(isIE){
var event = window.event;
}
var textbox = document.getElementById("txt1");
textbox.value += "\n> " + event.type;
textbox.value += "\n target is " + (event.target || event.srcElement).id;
textbox.value += "\n keyCode is " + event.keyCode;
textbox.value += "\n charCode is " + event.charCode;
var arrKeys = [];
if(event.shiftKey){ arrKeys.push("Shift");}
if(event.ctrlKey){ arrKeys.push("Ctrl");}
if(event.altKey){ arrKeys.push("Alt");}
textbox.value += "\n keys down are " + arrKeys;
}
顺序
字符键: keydown keypress keyup 非字符键: keydown keyup
当按住一个键不放时,两个事件逐个发生
HTML事件
load事件 页面完全载入后,在window对象上触发; 所有的框架都载入后,在框架集上触发;
<img/>完全载入后,在其上触发; <object/>元素,其完全载入后在其上触发
unload事件 上面的四种对象卸载时触发(在浏览从一个页面到另一个页面时,如点击链接到另一个
页面了或关闭窗口时)
abort事件 用户停止下载过程时,且<object/>对象还未完全载入,就在其上触发
error事件 javascript出错时,在window对象上触发; <img/>的指向图片无法载入时,在其上触发
<object/>元素无法载入时触发; 框架集中一个或多个无法载入时触发
select事件 用户选择了文本框中一个或多个字符时触发
change事件 文本框失去焦点时并且在它获取焦点后内容发生过改变时触发; 某个<select/>元素
值发生改变时触发
submit事件 点击提交时,在<form/>上触发
reset事件 点击重置时,在<form/>上触发
resize事件 窗口或框架大小改变时触发
scroll事件 用户在任何带滚动条的元素上卷动它时触发.<body/>元素包含载入页面的滚动条
focus事件 任何元素或者窗口本身获得焦点时触发
blur事件 任何元素或者窗口本身失去焦点时触发
对于resize事件,IE和Opera在窗口的大小一改变时就触发,而Mozilla则是等不再改变时才触发.而且最大化和最小化窗口时也会触发此事件
scroll事件中,可以通过使用document.body.scrollLeft document.body.scrollTop 来获得当前滚动框的顶点位置
变化事件
DOM标准虽然定义了变化事件,(是指添加节点等操作),但还没有浏览器实现了它.只列出:
DOMSubtreeModified 文档或元素的子树因为添加或删除节点而改变时触发
DOMNodeInserted 一节点作另一节点的子节点插入时触发
DOMNodeRemoved 同上
DOMNodeRemovedFromDocument 一个节点从文档中删除时触发
DOMNodeInsertedIntoDocument 同上