首页 > 代码库 > 13章 事件
13章 事件
支持情况 : 所有浏览器。
差异 :
浏览器 | 表现 |
IE5.5- | 最具体的元素->...->body->document |
IE9、Firefox、Chrome、Safari | 最具体的元素->...->body->html->document->window |
13.1.2 事件捕获 : document->html->body->...->最具体的元素
支持情况: IE9、Safari、Chrome、Opera、Firefox
不支持情况 : 所有老版本浏览器
事件捕获阶段 : 为截获事件提供机会
处于目标阶段 : 实际的目标接收到事件
事件冒泡阶段 : 冒泡阶段
会创建一个封装着元素属性值的函数;
this : 当前dom
event : 事件对象
扩展了作用域;
//形象说明作用域的扩展情况function(){ with(document){ with(this){ //HTML标签中的代码相当于在这里执行 } }}//表单的情况function(){ with(document){ with(this.form){ with(this){ //HTML标签中的代码相当于在这里执行 } } }}
方式一 : 直接在标签中嵌入JS代码
<input type=‘button‘ value=http://www.mamicode.com/‘Click Me‘ onclick="alert(‘Clicked‘)" />
方式二 : 调用其他地方定义的脚本
<script> function showMessage(){ alert(‘Hello world!‘); }</script><input type=‘button‘ value=http://www.mamicode.com/‘Click Me‘ onclick="showMessage()" />
解析不及时引发错误 : 如果函数被定义在最底部,如果用户在页面解析注册的方法之前就被调用将发生错误;
<!-- try-catch避免引发错误 --><input type=‘button‘ value=http://www.mamicode.com/‘Click Me‘ onclick=‘try{showMessage();}catch(e){}‘ />
扩展事件处理程序的作用域链在不同 浏览器中会导致不同结果;
HTML代码和JavaScript代码耦合。
DOM0级方法指定的事件处理程序被认为是元素的方法,因此程序中的this引用当前元素;
这种事件处理程序在事件流的冒泡阶段处理;
每个元素(包括window和document)都有自己的的事件处理程序。
var btn = document.getElementById(‘myBtn‘);btn.onclick = function(){ alert(this.id); //‘myBtn‘};btn.onclick = null; //删除通过DOM0级方法指定的事件处理程序
addEventListener() : 添加事件,3个参数,要处理的事件名、作为事件处理处理程序的函数、布尔值(true表示捕获阶段;false表示冒泡阶段)
依附元素的作用于;
可以添加多个事件处理程序,事件触发后按添加的顺序执行;
addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;
移除时传入的参数与添加处理程序使用相同的参数;
添加的匿名函数无法移除。
removeEventListener() : 移出
addEventListener()添加的事件处理程序,参数和
addEventListener()
保持一致
var btn = document.getElementById(‘myBtn‘);//添加多个事件处理程序btn.addEventListener(‘click‘, function(){ alert(this.id);},false);btn.addEventListener(‘click‘, function(){ alert(‘Hello World!‘);},false);//演示移除事件处理程序var handler = function(){ alert(this.id);};btn.addEventListener(‘click‘, handler, false);btn.removeEventListener(‘click‘, handler, false);
IE9 | Firefox | Safari | Chrome | Opera |
attachEvent() : 添加事件,两个参数,事件处理程序名称、事件处理函数
IE8-只支持事件冒泡,因此会被添加到冒泡阶段;
事件名带‘on‘前缀;
事件处理程序在全局作用域中运行,this等于window;
可以添加多个事件处理程序,事件触发后按与添加的相反的顺序执行;
attachEvent() 添加的事件处理程序只能使用detachEvent()来移除;
移除时传入的参数与添加处理程序使用相同的参数;
添加的匿名函数无法移除。
detachEvent() : 移除通过attachEvent()添加的事件处理函数
var btn = document.getElementById(‘myBtn‘);var handler = function(){ alert(this == window); //true};btn.attachEvent(‘onclick‘, handler);btn.detachEvent(‘onclick‘, handler);
IE | Opera |
/*** DOM2>IE>DOM0* param{object} element - dom节点对象* param{string} type - 事件名称* param{boolean} handler - 函数的引用*/var EventUtil = { //添加事件处理程序 addHandler: function(element, type, handler){ if(element.addEventListener){ //DOM2 element.addEventListener(type, handler, false); }else if(element.attachEvent){ //IE8- element.attachEvent(‘on‘+type, handler); }else{ //DOM0 element[‘on‘+type] = hanler; } }, //移除事件处理程序 addHandler: function(element, type, handler){ if(element.removeEventListener){ //DOM2 element.addEventListener(type, handler, false); }else if(element.detachEvent){ //IE8- element.detachEvent(‘on‘+type, handler); }else{ //DOM0 element[‘on‘+type] = null; } }};
所有浏览器都支持event对象,但支持方式不同;
只在事件处理程序执行期间存在,执行完毕后被销毁;
不同事件类型可用的属性和方法不同,都包括的成员如下:
event.type : 事件类型
var btn = document.getElementById(‘myBtn‘);var handler = function(event){ switch(event.type){ case "click": alert(‘Clicked‘); break; case "mouseover": event.target.style.backgroundColor = ‘red‘; break; case "mouseout": event.target.style.backgroundColor = ‘‘; break; }};btn.onclick = handler;btn.onmouseover = handler;btn.onmouseout = handler;
event.target : 事件的实际目标(最具体的那个元素)
event.currentTarget : 和this相同,注册事件的那个元素
event.eventPhase : 事件当前所在的事件流的阶段
1: 捕获阶段调用事件处理程序
2: 事件处理程序处在目标对象上
3: 冒泡阶段调用事件处理程序
var btn = document.getElementById(‘myBtn‘);//捕获阶段document.body.addEventListener(‘click‘, function(event){ alert(event.eventPhase); //1},true);//处于目标阶段btn.onclick = function(event){ alert(event.eventPhase); //2};//冒泡阶段document.body.addEventListener(‘click‘, function(event){ alert(event.eventPhase); //3},false);
event.preventDefault() : 取消默认行为
event.stopPropagation() : 立即停止事件在DOM层次中的传播,即取消进一步的事件捕获或冒泡
访问IE中的event对象的方式取决于指定事件处理程序的方法
window.event(DOM0级方法)
var btn = document.getElementById(‘myBtn‘);btn.onclick = function(){ var event = window.event; alert(event.type); //‘click‘};
作为参数对象(attachEvent())
var btn = document.getElementById(‘myBtn‘);btn.attachEvent(‘onclick‘, function(event){ alert(event.type); //‘click‘});
直接访问event(HTML中)
<input tyep=‘button‘ value=http://www.mamicode.com/‘Click Me‘ onclick=‘alert(event.type)‘ />
var EventUtil = { /** * 用来添加事件处理程序的方法 * param{object} element - dom * param{string} type - 事件名称 * param{function} handler - 函数引用 */ addHandler: function(element, type, handler){ if(element.addEventListener){ //DOM2 element.addEventListener(type, handler, false); }else if(element.attachEvent){ //IE8- element.attachEvent(‘on‘+type, handler); }else{ //DOM0 element[‘on‘+type] = hanler; } }, /** * 用来移除事件处理程序的方法 * param{object} element - dom * param{string} type - 事件名称 * param{function} handler - 函数引用 */ addHandler: function(element, type, handler){ if(element.removeEventListener){ //DOM2 element.addEventListener(type, handler, false); }else if(element.detachEvent){ //IE8- element.detachEvent(‘on‘+type, handler); }else{ //DOM0 element[‘on‘+type] = null; } }, /** * 获得事件对象的方法 * param{object} event - 事件处理程序执行时产生的事件对象(如果有的话) * return{object} 事件对象 */ getEvent: function(event){ return event ? event : window.event; }, /** * 获得触发事件的目标的方法 * param{event} event - 事件对象 * return{object} dom - 触发事件的节点 */ getTarget: function(event){ return event.target || event.srcElement; }, /** * 取消默认动作 * param{object} event -事件对象 */ preventDefault: function(event){ if(event.preventDefault){ event.preventDefault(); }else{ event.returnValue = http://www.mamicode.com/false; } }, /** * 阻止事件冒泡(或捕获) * param{object} event -事件对象 */ stopPropagation: function(event){ if(event.stopPropagation){ event.stopPropagation(); }else{ event.cancelBubble = true; } }};
btn.onclick = function(event){ event = EventUtil.getEvent(event); // 确保在不同浏览器都能获得event var target = EventUtil.getTarget(event); //确保获得target EventUtil.preventDefault(event); //确保清除默认动作 EventUtil.stopPropagatiom(event); //阻止传播 };
DOM2级事件
DOM3级事件(以DOM2为基础)
UI事件
焦点事件
鼠标事件
滚轮事件
文本事件
键盘事件
合成事件
变动事件
变动名称事件
HTML5定义的一组事件
DOM和BOM中实现的其它专有事件(没有规范)
事件名称 | DOM | 触发时机 | 备注 |
DOMActive | 任何元素 | 元素已经被用户操作激活 | 被DOM3废弃 |
load | window | 页面加载完后 | HTML事件 |
框架集 | 所有框架都加载完毕 | ||
<img> | 图像加载完毕 | ||
<object> | 嵌入的内容加载完毕 | ||
unload | window | 页面完全卸载 | HTML事件 |
<img> | 无法加载图片 | ||
框架集 | 所有框架都卸载 | ||
<object> | 嵌入的内容卸载完毕 | ||
abort | <object> | 用户停止下载,嵌入的内容没有加载完 | HTML事件 |
error | window | JavaScript错误 | HTML事件 |
<img> | 无法加载图像 | ||
<object> | 无法加载嵌入内容 | ||
框架集 | 有框架无法加载 | ||
select | <input> | 用户选择文本框一个或多个字符 | HTML事件 |
<textarea> | 用户选择文本框一个或多个字符 | ||
resize | window或框架 | 窗口或框架变化 | HTML事件 |
scroll | 带滚动条的元素 | 用户滚动带滚动条的元素中的内容 | HTML事件 <body>元素中包含加载 元素的滚动条 |
load事件
方式一: JS(推荐)
使用了跨浏览器的脚本;
传入的event不包含有关这个时间的任何附加信息;
兼容DOM时,event.target会被设置为document;IE不会为其设置srcElement属性;
"DOM2级事件"规范应该在document上而不是window上触发load事件,但所有浏览器都在window上面实现了该事件(确保向后兼容)。
EventUtil.addHandler(window, ‘load‘, function(event){ alert(‘Loaded!‘);});
方式二: 为元素添加onload属性
<!DOCTYPE html><html><head> <title>Load Event Example</title></head><body onl oad=‘alert(‘Loaded!‘)‘></body></html>
方式一
var image = document.getElementById(‘myImage‘);EventUtil.addHandler(image, ‘load‘, function(event){ event = EventUtil.getEvent(event); alert(EventUtil.getTarget(event).src);});
方式二
<img src=http://www.mamicode.com/‘smile.gif‘ onl oad=‘alert(‘Image loaded.‘)‘>
要在window上的onload事件触发后才添加DOM中,否则document.body会报错;
一旦设置了src属性,新创建的图像就开始加载图像,和是否添加到文档中无关;
方式一: DOM的方式
[IE8-]没有添加到DOM中的节点触发load事件时不会生成event对象。
EventUtil.addHandler(window, ‘load‘, function(event){ var image = document.createElement(‘img‘); EventUtil.addHandler(image, ‘load‘, function(event){ event = EventUtil.getEvent(event); alert(EventUtil.getTarget(event).src); }); document.body.appendChild(image); image.src = ‘smile.gif‘;});
方式二: Image对象
可以像使用<img>元素一样使用Image对象(并非所有浏览器都将Image对象实现为<img>);
无法添加到DOM中;
【IE8- 】Image对象触发load事件不会生成event对象。
EventUtil.addHandler(window, ‘load‘, function(){ var image = new Image(); EventUtil.addHandler(image, ‘load‘, function(event){ alert(‘Imaeg loaded!‘); });});
指定src属性并将元素添加到文档后才开始下载。
EventUtil.addHandler(window, ‘load‘, function(){ var script = document.createElement(‘script‘); EventUtil.addHandler(script, ‘load‘, function(event){ alert(‘Loaded‘); }); script.src = http://www.mamicode.com/‘exaple.js‘; document.body.appendChild(script);});
浏览器版本 | script元素onload事件 | event.target |
大多数浏览器 | 支持 | <script>节点 |
Firefox3- | 支持 | document |
IE8- | 不支持 |
和script类似
IE | Opera |
发生时机举例:只要用户从一个页面切换到另外一个页面,就会发生unload事件;
用途举例:清除引用避免内存泄漏;
DOM2级事件规定应该在<body>元素而不是window对象上触发unload事件。
方式一: JS
EventUtil.addHandler(window, ‘unload‘, function(event){ alert(‘Unloaded‘);});
方式二: HTML
<!DOCTYPE html><html><head> <title>Unloaded</title></head><body onunload="alert(‘unloaded!‘)"></body></html>
浏览器最大化最小化时也会触发resize事件。
方式一: JS
EventUtil.addHandler(window, ‘resize‘, function(event){ alert(‘Resized‘);});
方式二: HTML
<!DOCTYPE html><html><head> <title>Unloaded</title></head><body onresize="alert(‘resized!‘)"></body></html>
event差异
浏览器 | event.target | 备注 |
兼容DOM的 | document | |
IE8- | event没有任何属性 |
行为差异
浏览器 | 触发时间 |
IE、Safari、Chrome、Opera | 窗口变化1像素时 |
Firefox | 用户停止调整窗口大小时 |
在window对象上触发,表现的是页面上元素的变化。
模式 | 浏览器 | 元素 | 具体表现 |
混杂模式 | 所有 | body | scrollLeft和scrollTop |
标准模式 | Safari | body | 跟踪滚动位置 |
其它 | html | 跟踪滚动位置 |
//输出页面的垂直滚动位置,根据不同模式使用不同的元素EventUtil.addHandler(window, ‘scroll‘, function(event){ if(document.compatMode == ‘CSSCompat‘){ alert(document.documentElement.scrollTop); }else{ alert(document.body.scrollTop); }});
触发: 页面获得或失去焦点;
使用: 利用这些事件并与document.hasFocus()方法及document.activeElement属性配合来知晓用户在页面上的行踪;
顺序:以焦点由A元素移动到B元素为例
focusout(A)
focusin(B)
blur(A)
DOMFocusOut(A)
focus(B)
DOMFocusIn(B)
检测支持情况
焦点事件名 | 冒泡 | 触发 | 兼容性 | 备注 |
blur | 否 | 失去焦点 | 所有 | DOM3级事件(来自IE) |
focus | 获得焦点 | DOM3级事件(来自IE) | ||
DOMFocusIn | 是 | 获得焦点 | Opera | DOM3级事件中用focusin取代 |
DOMFocusOut | 失去焦点 | DOM3级事件中用focusout取代 | ||
focusin | 获得焦点 | IE5.5+、Safari5.1+、 Opera11.5+、Chrome | ||
focusout | 失去焦点 |
鼠标/滚轮事件名称 | 冒泡 | 触发 | 兼容性 | 备注 |
click | 是 | 单机主鼠标按钮(通常是左键)或键盘回车键 | ||
dbclick | 双击主鼠标按钮 | 非DOM2 | ||
mousedown | 用户按下任意鼠标按钮时 | |||
mouseenter | 否 | 鼠标光标从元素外部首次移动到元素范围之内 | IE、Firefox9+、Opera(非DOM2 ) | 非子元素 |
mouseleave | 鼠标光标移动到元素之外 | |||
mousemove | 是 | 鼠标光标在元素内移动时重复触发 | 非键盘 | |
mouseout | 从一个元素移动到里一个元素(父/子/兄弟) | |||
mouseover | 从目标元素外部移动到另一个元素边界内 | |||
mouseup | 释放鼠标按钮 |
冒泡可以被取消,但会影响其他事件;
事件执行顺序(以双击鼠标主键为例):
标准 | IE8(会跳过括号中的时间) |
|
|
click和dbclick事件会依赖其它先行时间的触发;mousedown和mouseup不受其它事件影响;
检测
DOM2
var isSupported = document.implementation.hasFeature(‘MouseEvents‘, ‘2.0‘);
DOM3
var isSupported = document.implementation.hasFeature(‘MouseEvent‘, ‘2.0‘);
属性 | 作用 | 兼容性 | 特点 |
event.clientX | 事件发生时鼠标指针在视口中的水平坐标 | 所有 | 不包括滚动的距离 |
event.clientY | 事件发生时鼠标指针在视口中的垂直坐标 |
var div = document.getElementByid(‘myDiv‘);EventUtil.addHandler(div, ‘click‘, function(event){ event = EventUtil.getEvent(event); alert(‘Client coordinates:‘ + event.clientX + ‘,‘ + event.clientY);});
属性 | 作用 | 兼容性 | 特点 |
event.pageX | 事件发生时鼠标指针在页面中的水平坐标 | IE8-之外 | 包括滚动的距离 |
event.pageY | 事件发生时鼠标指针在页面中的垂直坐标 |
var div = document.getElementByid(‘myDiv‘);EventUtil.addHandler(div, ‘click‘, function(event){ event = EventUtil.getEvent(event); var pageX = event.pageX, pageY = event.pageY; if(pageX === undefined){ pageX = event.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft); pageY = event.clientY + (document.body.scrollTop || document.documentElement.scrollTop); } alert(‘Page coordinates:‘ + pageX + ‘,‘ + pageY);});
var div = document.getElementByid(‘myDiv‘);EventUtil.addHandler(div, ‘click‘, function(event){ event = EventUtil.getEvent(event); alert(‘Page coordinates:‘ + event.pageX + ‘,‘ + event.pageY);});
属性 | 作用 | 兼容性 | 特点 |
event.screenX | 事件发生时鼠标指针在屏幕中的水平坐标 | IE8-之外 | 包括滚动的距离 |
event.screenY | 事件发生时鼠标指针在屏幕中的垂直坐标 |
var div = document.getElementByid(‘myDiv‘);EventUtil.addHandler(div, ‘click‘, function(event){ event = EventUtil.getEvent(event); alert(‘screen coordinates:‘ + event.screenX + ‘,‘ + event.screenY);});
修改键 | DOM规定的对应属性 | 兼容性 |
Shift | event.shiftKey | 所有(IE8-除外) |
Ctrl | event.ctrlKey | |
Alt | event.altKey | |
meta(win或Cmd) | event.metaKey |
//如果某个修改键被按下,event中对应的属性值为truevar div = document.getElementById(‘mDiv‘);EventUtil.addHandl(div, ‘click‘, function(event){ event = EventUtil.getEvent(event); var keys = new Array(); if(event.shiftKey){ keys.push(‘shift‘); } if(event.altKey){ keys.push(‘alt‘); } if(event.ctrlKey){ keys.push(‘ctrl‘); } if(event.metaKey){ keys.push(‘meta‘); } alert(‘Keys:‘ + keys.join(‘,’));} );
获取相关元素:
event的属性 | 事件 | 属性值 | 触发时机 | 兼容性 |
relatedTarget | mouseover | A元素的dom | 鼠标从A元素进入B(目标)元素 | IE8-不支持 |
mouseout | B元素的dom | 鼠标从A(目标)元素离开 | ||
fromElement | mouseover | A元素的dom | 鼠标从A元素进入B(目标)元素 | IE(包括IE8-) |
toElement | mouseout | B元素的dom | 鼠标从A(目标)元素离开 |
var EventUtil = { //省略其它代码 /** * 跨浏览器获得相关元素的方法 */ getRelatedTarget: function(event){ if(event.relatedTarget){ return event.relatedTarget; }else if(event.toElement){ return event.toElement; }else if(event.fromElement){ return null; } }, //省略其它代码};
var div = document.getElementById(‘myDiv‘);EventUtil.addHandler(div, ‘mouseout‘, function(){ event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); var relatedTarget = EventUtil.getRelatedTarget(event); alert(‘Mouse out of ‘ + target.tagName + ‘ to ‘ + relatedTarget.tagName);});
event.button | DOM | IE8- |
0 | 没有按下按钮 | 主 |
1 | 主 | 中 |
2 | 次 | 次 |
3 | 主+次 | |
4 | 中 | |
5 | 主+中 | |
6 | 次+中 | |
7 | 主+中+次 |
var EventUtil = { //省略其它代码 /** * 检测是否兼容DOM并规范化对相应的值规范化 */ getButton: function(event){ if(document.implementation.hasFeature(‘MouseEvents‘, ‘2.0‘)){ return event.button; }else{ switch(event.button){ case 0: case 1: case 3: case 5: case 7: return 0; case 6: return 2; case 4: return 1; } } }, //省略其它代码};var div = document.getElementById(‘myDiv‘);EventUtil.addHandler(div, ‘mousedown‘, function(event){ event = EventUtil.getElement(event); alert(EventUtil.getButton(event));});
DOM2级事件 | IE | ||||
event属性 | 类型 | 备注 | event属性 | 类型 | 备注 |
detail | number | 给定位置上发生点击的数量 | altLeft | boolean | 是否按了Alt |
ctrlLeft | boolean | 是否按了Ctrl | |||
offSetX | number | 光标相对于目标元素边界的x坐标 | |||
offSetY | number | 光标相对于目标元素边界的y坐标 | |||
shiftLeft | boolean | 是否按下shift键 |
IE6首先实现
event属性 | 浏览器 | 冒泡到 | 表现 |
wheelDelta | IE8 | document | 向前滚动120的倍数;向后滚动-120的倍数 |
IE9、Opera、Chrome、Safari | window |
//解决Opera 9.5之前的版本wheelDelta值正负点到的问题EventUtil.addHandler(document, ‘mousewheel‘, function(event){ event = EventUtil.getEvent(event); var delta = (client.engine.opera && client.opera < 9.5 ?-event.wheelDelta.opera:event.wheelDelta); alert(delta);});
/*** 兼容opera9.5-的获取wheelDelta值得方法*/var EventUtil = { //省略了其它代码 getWheelDelta: function(event){ if(event.wheelDelta){ return (client.engin.opera && client.engin.opra < 9.5 ? -event.wheelDelta : event.wheelDelta); }else{ return -event.detal * 40; } },};
不支持dbclick事件。双击浏览器窗口会放大画面,而且没有办法改变;
轻击可单击元素会触发mousemove;
mousemove事件也会触发mouseover和mouseout事件;
两个手指放在屏幕上且页面随手指一动而滚动时会触发mousewheel和scroll事件。
事件名 | 不推荐的原因 |
click之外的鼠标事件 | 无法通过键盘触发 |
onmousedown | 屏幕阅读器无法触发该事件 |
onmouseover | |
dbclick | 无法通过键盘触发 |
键盘事件(3)
位数 77DOM0 : 对键盘事件的支持主要遵循DOM0级;
DOM2 : 最终定稿时删除了相应的内容;
DOM3 : 为键盘事件制定了规范,IE9率先实现。
键盘事件 | 触发 | 表现 | 兼容性 |
keydown | 按下任意键 | 按住不放会重复触发 | |
keypress | 按下字符键(包括Esc) | Safari3.1-(非字符键也会触发) | |
keyup | 释放键盘上的键 |
文本事件(1)
文本事件 | 触发 | 表现 | 兼容性 |
textInput | 文本插入文本框之前 | keydown->keypress->textInput->keyup |
event属性 | 对应事件 | 值 | 兼容性 |
keyCode | keydown 和 keyup | ASCLL码中对应小写字母或数字的编码相同(分号按键存在兼容性问题) | DOM和IE |
var textbox = document.getElementById(‘myText‘);EventUtil.addHandler(textbox, ‘keyup‘, function(event){ event = EventUtil.getEvent(event); alert(event.keyCode);});
event属性 | 对应事件 | 值 | 兼容性 |
charCode | keypress | 按下的键对应的ASCLL | IE9、Firefox、Chrome、Safari |
不考虑兼容
var textbox = document.getElementById(‘myText‘);EventUtil.addHandler(textbox, ‘keypress‘, function(event){ event = EventUtil.getEvent(event); alert(event.charCode);});
考虑兼容
var EventUtil = { //省略的代码 getCharCode: function(event){ if(typeof event.charCode == ‘number‘){ reutrn event.charCode; }else{ reutrn event.keyCode; } }, //省略的代码};
event中删除的成员
event属性 | 对应事件 | 值 | 兼容性 |
charCode | keypress | 按下的键对应的ASCLL | IE9、Firefox、Chrome、Safar |
event中添加的成员
event成员 | 对应事件 | 值 | 兼容性 |
key | keypress | 文本字符或键的名字(非字符) | IE9支持 |
char | 文本字符或null(非字符) | IE9不支持 | |
keyIdentifier(非DOM3) | ‘U+000‘字符串或键的名字(非字符) | Sfari 5 和 Chrome | |
location | number(代表键盘区域的位置) | IE9 | |
keyLocation | 有BUG | Safari和Chrome | |
getModifierState() | boolean,检测某个修改键是否被按下 | IE9唯一支持 |
//跨浏览器获得键盘字符var textbox = document.getElementById(‘myText‘);EventUtil.addHandler(textbox, ‘keypress‘, function(event){ event = EventUtil.getEvent(event); var identifier = event.key || event.keyIdentifier; if(identifier){ alert(identifier); }});
//检测某个修改键是否被按下var textbox = document.getElementById(‘myText‘);EventUtil.addHandler(textbox, ‘keypress‘, function(event){ event = EventUtil.getEvent(event); if(event.getModifiedState){ alert( event.getModifiedState(‘Shift‘)); }});
相关属性 | 有效元素 | 事件 | 值 | 来源 | 兼容性 |
event.data | 可编辑区域 | textInput(在可编辑区域输入字符时) | 用户输入的字符(非字符编码) | DOM3级事件 | IE9+、Safari、Chrome |
event.textInput | 0-9(表示输入到文本框中的方式) | 仅IE |
//获得用户输入的字符var textbox = document.getElementById(‘myText‘);EventUtil.addHandler(textbox, ‘textInput‘, function(event){ event = EventUtil.getEvent(event); alert(event.data);});
var isSupported = document.implementation.hasFeature(‘CompositionEvent‘);
DOM2级变动事件
变动事件 | 触发 | 补充 |
DOMSubtreeModified | 在DOM结构中发生任何变化时 | 也就是说其它任何变动事件发生时都会触发 |
DOMNodeInstead | 一个节点被作为子节点插入到另一个节点 | |
DOMNodeRemoved | 将节点从父节点移除时 | |
DOMNodeInsertedIntoDocument | 节点被插入文档或通过子树间接插入文档 | 在DOMNodeInstead 之后触发 |
DOMNodeRemovedFromDocument | 节点从文档移除或通过子树间接移除之前 | 在DOMNodeRemoved之后触发 |
DOMAttrModified | 特性被修改之后 | |
DOMCharacterDataModified | 文本节点的值发生变化 |
监测浏览器对变动事件的支持
var isSupported = document.implementation.hasFeature(‘MutationEvents‘, ‘2.0‘);
事件(按触发先后顺序) | 相关属性 | 属性值 | dom位置 | 触发时机 | 冒泡 | 备注 |
DOMNodeRemoved | event.realtedNode | 父节点 | 可以在DOM的任何层次处理 | 使用removeChild()或replaceChild()删除节点 | 是 | |
event.target | 被删除的节点 | |||||
DOMNodeRemovedFromDocument | 被删除的子节点本身 | 被移除的所有子节点会相继触发 | 否 | 因为不会冒泡,所有必需给子节点指定事件处理程序才会触发 |
事件(按触发先后顺序) | 相关属性 | 属性值 | dom位置 | 冒泡 | 触发时机 | 备注 |
DOMNodeInserted | event.relatedNode | 对父节点的引用 | 各个层次 | 是 | appendChild()、replaceChild()、insertBefore() | |
DOMNodeInsertedIntoDocument | event.target | 被插入的节点 | 被插入的节点 | 否 | 必须在插入节点前为其添加事件处理程序 | |
DOMSubtreeModified | 新插入节点的父节点 |
触发 | 用途 | 冒泡 | 屏蔽方式 | 备注 |
右键单击(win);ctrl+单击(mac) | 如何确定显示上下文菜单或如何自定义上下文菜单 | 是 | DOM:event.preventDefault(); IE:event.returnValue = http://www.mamicode.com/false; |
EventUtil.addHandler(window, ‘load‘, function(event){ var div = document.getElementById(‘myDiv‘); EventUtil.addHandler(div, ‘contextmenu‘, function(event){ event = EventUtil.getEvent(event); EventUtil.preventDefault(event); var menu = document.getElementById(‘myMenu‘); menu.style.left = event.clientX + ‘px‘; menu.style.top = event.clientY + ‘px‘; menu.style.visibility = ‘‘visable; }); EventUtil.addHandler(document, ‘click‘, function(event){ document.getElementById(‘myMenu‘).style.visibility = ‘hidden‘; });});
//为了显示这个弹出的对话框,必需将event.returnValue的值设置为要显示给用户的字符串。EventUtil.addHandler(window, ‘beforeunload‘, function(event){ event = EventUtil.getEvent(event); var message = ‘确定卸载页面吗?‘; event.returnValue = http://www.mamicode.com/message; return message;});
支持在页面下载的早期添加事件处理程序;
事件会冒泡到window,但目标实际上是document;
event.target值为document,此外event没有额外的信息。
IE9+ | Firefox | Chrome | Safari3.1+ | Opera9+ |
//会在load事件之前触发EventUtil.addHandler(document, ‘DOMContentLoaded‘, function(event){ alert(‘Content loaded‘);});
不支持DOMContentLoaded的浏览器:
//在当前JS处理完后立即运行,无法保证在所有环境下都早于load事件被触发。setTime(function(){ //在此添加事件处理程序},0);
readyState属性值 | 含义 |
uninitialized | 对象存在但未初始化 |
loading | 对象正在加载数据 |
loaded | 对象加载数据完毕 |
interactive | 可以操作对象了,但还没有完全加载 |
complete | 对象已经加载完毕 |
对象不一定经历所有阶段,属性变化也不总是连续的;
因此readystatechange 事件经常会少于4次;
与load事件一起使用时,无法预测两个事件触发的先后顺序。
EventUtil.addHandler(document, ‘readystateChange‘, function(event){ if(document.readyState == ‘interactive‘){ alert(‘Content loaded‘); }});
EventUtil.addHandler(document, ‘readystatechange‘, function(event){ if(document.readyState == ‘interactive‘ || document.readyState == ‘complete‘){ EventUtil.removeHandler(document, ‘readystatechange‘, arguments.callee); alert(‘Content loaded‘); }});
IE | Firefox4+ | Opera |
EventUtil.addHandler(window, ‘load‘, function(){ var script = document.createElement(‘script‘); EventUtil.addHandler(script, ‘readystatecange‘, function(event){ event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); if(target.readyState == ‘loaded‘){ EventUtil.removeHandler(target, ‘readystatechange‘, argument.callee); } }); script.src = http://www.mamicode.com/‘example.js‘; docuemnt.body.appendChild(script);});
EventUtil.addHandler(window, ‘load‘, function(){ var link = document.createElement(‘link‘); link.type = ‘text/css‘; link.rel = ‘stylesheet‘; EventUtil.addHandler(script, ‘readystatecange‘, function(event){ event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); if(target.readyState == ‘loaded‘){ EventUtil.removeHandler(target, ‘readystatechange‘, argument.callee); } }); link.href = http://www.mamicode.com/‘example.css‘; docuemnt.getElementsByTagName(‘head‘)[0].appendChild(link);});
事件名 | 触发 | 目标 | 绑定事件处理 | event.persisted | 兼容性 |
pageshow | 重新加载:load事件触发后 | document | window | false | Firefox Safari5+ Chrome Opera |
bfcache中的页面:页面状态完全恢复时 | true | ||||
pagehide | 浏览器卸载页面时 | 会将该属性设为true |
观察pageshow事件
(function(){ var showCount = 0; EventUtil.addHandler(window, ‘load‘, function(){ alert(‘Load fired‘); }); EventUtil.addHandler(window, ‘pageshow‘, function(){ showCount++; alert(‘Show has been fired ‘ + showCount + ‘ times.‘); });})();
观察pagehide事件
EventUtil.addHandler(window, ‘pagehide‘, function(event){ alert(‘Hiding.Persisted?‘ + event.persisted);});
触发 | 对象 | 属性 | 属性值 | 来源 | 兼容性(属性) | 兼容性(事件) |
URL参数列表(包括后面的所有字符串)发生变化时 | window | oldURL | 变化前的URL | HTML5 | Firefox6+、Chrome、Opera | IE8+、Firefox3.6+、Safari5+、Chrome、Opera10.6+ |
newURL | 变化后的URL |
捕获事件
//Firefox6+、Chrome、OperaEventUtil.addHandler(window, ‘hashchange‘, function(event){ alert(‘Old URL:‘ + event.oldURL + ‘\nNew URL:‘ + event.newURL);});//使用location对象确定当前的参数列表(考虑兼容不支持oldURL和newURL的浏览器)EventUtil.addHandler(window, ‘hashChange‘, function(event){ alert(‘Current hash:‘ + location.hash);});
检测支持情况(考虑了IE8和IE7在文档模式下运行会发生BUG的问题)
var isSupported = (‘onhashchange‘ in window) &&(document.documentMode === undefined || document.documentMode > 7);
触发 | 相关属性 | 支持 | 来源 | |
手机屏幕横纵切换方式变化 | window.oritentation | Safari | 苹果公司 |
window.oritentation
window.oritentation | 含义 | 备注 |
0 | 肖像模式 | |
90 | 向左旋转为横向 | |
-90 | 向右旋转为横向 | |
180 | 头向下 | 无设备支持 |
方式一:
EventUtil.addHandler(window, ‘load‘, function(event){ var div = document.getElementById(‘myDiv‘); div.innerHTML = ‘Current orentation is ‘ + window.orientation; EventUtil.addHandler(window, ‘orientationchange‘, function(event){ div.innerHTML = ‘current orientation is ‘ + window.orientation; });});
触摸事件 | 触发 | 备注 | ||
touchstart | 手指触摸屏幕时触发 | |||
touchmove | 手指在屏幕上连续地触发 | |||
touchend | 手指从屏幕上移开时 | |||
13章 事件