DOM3 级事件规定了这些事件:
事件 | 说明 |
---|---|
焦点 | 当元素获得或失去焦点时触发。 |
鼠标 | 用户通过鼠标在页面上进行操作时触发。 |
滚轮 | 使用鼠标滚轮(或类似设备)时触发。 |
文本 | 在文档中输入文本时触发。 |
键盘 | 用户通过键盘在页面上进行操作时触发。 |
合成 | 使用 IME(Input Mehtod Editor)输入字符时触发。 |
变动 | 底层 DOM 结构发生变化时触发。 |
名称变动 | 元素或属性名改变时触发。(已废弃) |
DOM 规范为了保证向后兼容,已经保留了 UI 事件。有这些 UI 事件:
事件名 | 说明 |
---|---|
DOMActivate | 元素已经被用户的相关操作(鼠标或键盘)激活,DOM3 已废弃。 |
load | 在页面完全加载时在 window 上触发,当所有框架都加载完毕时在框架集上触发,当图像加载完毕时在 上触发,当嵌入内容加载完毕时在 元素上触发。 |
unload | 在页面完全卸载时在 window 上触发,当所有框架都卸载完毕时在框架集上触发,当嵌入内容卸载完毕时在 元素上触发。 |
abort | 用户停止了下载,这是如果嵌入的内容还未加载完,就在 元素上触发。 |
error | 发生 JavaScript 错误时在 window 上触发,当无法加载图像时在 上触发,当无法加载嵌入内容时在 元素上触发,当有一个或多个框架无法加载时在框架集上触发。 |
select | 当用户选择 或 中的一个或多个字符时触发。 |
resize | 当窗口或框架的大小发生变化时在 window 或框架上触发。 |
scroll | 当用户滚动带有滚动条的元素中的内容时,在该元素上触发。 |
多数事件都与 window 对象或者表单控件有关。
除了 DOMActivate 外,其他事件在 DOM2 级事件中都归为 HTML 事件,这样确定浏览器是否支持 DOM2 级事件规定的 HTML 事件:
var isSupported = document.implementation.hasFeature("HTMLEvents","2.0");
这样确定浏览器是否支持 DOM3 级事件规定的 UI 事件:
var isSupported = document.implementation.hasFeature("UIEvent","3.0");
当页面完全加载时就会触发 window 上的 load 事件。有两种定义 onload 事件的方法。第一种是通过 JavaScript 来指定的:
<script type="text/javascript" src="EventUtil.js">script>
<script type="text/javascript">
EventUtil.addHandler(window, "load", function (event) {
console.log("Loaded!");
});
script>
EventUtil.js 请参见 这里
第二种是在 元素中添加一个 onload 属性:
<body onload="console.log('Loaded!')">
body>
建议尽量使用 JavaScript 的方式来指定!
注意: DOM2 级事件规范要求在 document 上触发 load 事件。但所有的浏览器为了确保向后兼容,都在 window 上实现了这一事件!
也可以为图像指定 onload 事件:
<img src="http://avatar.csdn.net/D/4/8/1_deniro_li.jpg" onload="console.log('Image loaded.')">
上面的例子也可以用 JavaScript 来实现:
<img id="myImage" src="http://avatar.csdn.net/D/4/8/1_deniro_li.jpg"
>
<script type="text/javascript" src="EventUtil.js">script>
<script type="text/javascript">
var image = document.getElementById("myImage");
EventUtil.addHandler(image, "load", function (event) {
event = EventUtil.getEvent(event);
console.log(EventUtil.getTarget(event).src);
});
script>
创建新的 元素时,可以为其指定一个事件,但必须在指定 src 属性之前先指定事件,这样才能在图像加载完毕时给出提示:
<script type="text/javascript">
EventUtil.addHandler(window, "load", function (event) {
var image = document.createElement("img");
EventUtil.addHandler(image, "load", function (event) {//先指定事件
event = EventUtil.getEvent(event);
console.log(EventUtil.getTarget(event).src);
});
document.body.appendChild(image);
image.src = "http://avatar.csdn.net/D/4/8/1_deniro_li.jpg";//再指定 src
});
script>
注意,新的图像元素只要设置了 src 属性就会开始下载!
通过的功能也可以使用 DOM0 级的 Image 对象来实现。在 DOM 出现之前,开发人员经常使用 Image 对象为客户端预加载图像,只不过 Image 对象无法添加到 DOM 树中:
<script type="text/javascript">
EventUtil.addHandler(window, "load", function (event) {
var image = new Image();
EventUtil.addHandler(image, "load", function (event) {//先指定事件
console.log("Image loaded!");
});
image.src = "http://avatar.csdn.net/D/4/8/1_deniro_li.jpg";//再指定 src
});
script>
注意: 在不属于 DOM 文档的图像(未添加到文档的 元素和 Image 对象)上触发 load 事件时,IE8 及之前的版本是不会生成 event 对象的!IE9 修复了这个问题。
还有一些元素以非标准的方式支持 load 事件。IE9+、Firefox、Opera、Chrome 和 Safari 3+ 及更高版本中, 元素也会触发 load 事件,这样做可以方便开发人员确定动态加载的 JavaScript 文件是否已经加载完毕。只有设置了
元素的 src 属性并将该元素添加到文档后,才会开始下载 JavaScript 文件:
EventUtil.addHandler(window, "load", function (event) {
var script = document.createElement("script");
EventUtil.addHandler(script, "load", function (event) {
console.log("Loaded");
});
script.src = "http://c.csdnimg.cn/pubfooter/js/tracking.js";
document.body.appendChild(script);
IE、Chrome 和 Opera 还支持在 元素上的 load 事件,以便开发人员确定样式表是否已经加载完毕:
//动态添加样式表
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
EventUtil.addHandler(link, "load", function (event) {
console.log("css loaded");
});
link.href = "http://c.csdnimg.cn/public/common/toolbar/css/index.css"
document.getElementsByTagName("head")[0].appendChild(link);
只有指定了 href 属性并且添加到文档中的 元素才会开始下载样式表。
当文档被完全卸载后就会触发。用户从一个页面切换到另一个页面,也会发生 unload 事件。一般利用这个事件来清除引用,避免内存泄漏。也有两种指定 unload 事件的方法,第一种是使用 JavaScript 来指定:
EventUtil.addHandler(window, "unload", function(event){
console.log("Unloaded");
});
此时的 event 对象在兼容 DOM 的浏览器中只有 target 属性(值为 document)。IE8 及之前的版本则为这个对象提供了 srcElement 属性。
第二种方式是,为 元素添加 onunload 属性:
<body onunload="alert('Unloaded!')">
body>
注意: 根据 DOM2 级事件的规范,应该在 元素上触发 unload 事件。但所有的浏览器为了确保向后兼容,都在 window 上实现了 unload 事件。
当浏览器窗口的宽高发生变化时,就会触发 resize 事件。它会在 window 上触发,可以通过 JavaScript 或 元素中的 onresize 属性来指定,还是推荐使用 JavaScript 来指定:
EventUtil.addHandler(window, "resize", function(event){
console.log("Resized");
});
此时的 event 对象在兼容 DOM 的浏览器中只有 target 属性(值为 document)。IE8 及之前的版本没有提供任何属性!
何时会触发 resize 事件,不同的浏览器有不同的机制。IE、Safari、Chrome 和 Opera 会在浏览器窗口变化了 1 个像素时,触发 resize 事件,然后随着变化不断重复触发。Firefox 只会在用户停止调整窗口大小时,才会触发 resize 事件。这个事件可能会被频繁地执行,因此不要在 resize 事件中加入具有大计算量的代码,这会导致浏览器的反应明显变慢。
注意: 最大化或最小化浏览器窗口,都会触发 resize 事件。
虽然 scroll 事件是在 window 对象上触发的,但它实际表示的是页面中相应的元素发生了变化。在混杂模式下,可以通过 元素的 scrollLeft 和 scrollTop 来监控这一变化;在标准模式下,除了 Safari 之外的所有浏览器都会通过
元素来监控这一变化(Safari 中仍是基于
元素来监控的):
<script type="text/javascript">
EventUtil.addHandler(window, "scroll", function (event) {
if (document.compatMode == "CSS1Compat") {
console.log(document.documentElement.scrollTop);
} else {
console.log(document.body.scrollTop);
}
});
script>
与 resize 事件类似, scroll 事件也会在文档滚动期间被重复地触发,所以要保持 scroll 事件足够简单!
焦点事件会在页面获得或者失去焦点时触发。利用焦点事件并与 document.hasFocus() 方法以及 document.activeElement 属性相配合,可以获知用户在页面上的行踪,有这些焦点事件:
焦点事件 | 说明 |
---|---|
blur | 元素失去焦点时触发。它不会冒泡,所有浏览器都支持。 |
DOMFocusIn | 元素获得焦点时触发。它与 HTML 事件的 focus 等价,但它还支持冒泡。只得到 Opera 支持,遭到 DOM3 级事件废弃。 |
DOMFocusOut | 元素失去焦点时触发。它与 HTML 事件的 blur 等价。只得到 Opera 支持,遭到 DOM3 级事件废弃。 |
focus | 元素获得焦点时触发。它不会冒泡,所有浏览器都支持。 |
focusin | 元素获得焦点时触发。它与 HTML 事件的 focus 等价,但它还支持冒泡。IE5.5+、Safari 5.1+、Opera 11.5+ 和 Chrome 都支持。 |
focusout | 元素失去焦点时触发。它与 HTML 事件的 blur 等价。IE5.5+、Safari 5.1+、Opera 11.5+ 和 Chrome 都支持。 |
focus 和 blur 最大的问题是不冒泡,所以 IE 的 focusin 和 focusout 才被 DOM3 级事件采纳为标准。
当焦点从页面中的一个元素移动到另一个元素时,会依次触发这些事件:
1. focusout 在失去焦点的元素上触发。
2. focusin 在获得焦点的元素上触发。
3. blur 在失去焦点的元素上触发。
4. DOMFocusOut 在失去焦点的元素上触发。
5. focus 在获得焦点的元素上触发。
6. DOMFocusIn 在获得焦点的元素上触发。
使用以下代码可以确定浏览器是否支持这些事件:
var isSupported = document.implementation.hasFeature("FocusEvent","3.0");
DOM3 级事件定义了 9 个鼠标事件:
鼠标事件 | 说明 |
---|---|
click | 单击主鼠标按钮(一般是最左边的按钮)或者按下回车键时触发。 |
dblclick | 双击主鼠标按钮时触发。 |
mousedown | 按下任意鼠标按钮时触发。不能通过键盘触发这一事件。 |
mouseenter | 鼠标的光标从元素外部首次移动到元素范围内时触发。它不冒泡,而且光标移动到后代元素上也不会再触发。IE、Firefox 9+ 和 Opera 支持。 |
mouseleave | 位于元素内的鼠标光标移动到元素范围外时触发。。IE、Firefox 9+ 和 Opera 支持。 |
mousemove | 鼠标指针在元素内移动时重复地触发。不能通过键盘触发这一事件。 |
mouseout | 鼠标指针位于一个元素内,然后将其移动另一个元素时触发。这里说的另一个元素可能位于前一个元素外部,也可能是这个元素的子元素。不能通过键盘触发这一事件。 |
mouseover | 鼠标指针位于元素外部,让后将其首次移入另一个元素边界之内时触发。不能通过键盘触发这一事件。 |
mouseup | 释放鼠标按钮时触发。不能通过键盘触发这一事件。 |
页面上的所有元素都支持鼠标事件。除了 mousedown 和 mouseup 之外,其他所有鼠标事件都会冒泡,它也可以被取消。
只有在同一个元素上相继触发 mousedown 和 mouseup 事件,才会触发 click 事件;如果 mousedown 和 mouseup 事件有一个被取消,那么就不会触发 click 事件。只有触发两次 click 事件,才会触发一次 dblclick 事件。它们的触发顺序是这样的:
1. mousedown
2. mouseup
3. click
4. mousedown
5. mouseup
6. click
7. dblclick
click 和 dblclick 事件会依赖于其他先行事件。
IE8 及之前的版本有一个 bug,就是在双击事件中,会跳过第二个 mousedown 和 click 事件。IE9 修复了这一 bug。
使用以下代码可以确定浏览器是否支持这些 DOM2 事件(除 dbclick、mouseenter 和 mouseleave 之外):
var isSupported = document.implementation.hasFeature("MouseEvents","2.0");
使用以下代码可以确定浏览器是否支持这些 DOM3 事件:
var isSupported = document.implementation.hasFeature("MouseEvent","3.0");
注意:这里是 “MouseEvent”!
还有一个 mousewheel 事件,它会跟踪鼠标的滚轮。
鼠标事件都是在浏览器视口的特定位置上发生的。这些位置信息保存在事件对象的 clientX 和 clientY 中。所有浏览器都支持这两个属性,它们表示事件发生时鼠标指针在视口中的水平和垂直坐标:
<div id="myDiv">点我div>
<script type="text/javascript" src="EventUtil.js">script>
<script type="text/javascript">
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function (event) {
event = EventUtil.getEvent(event);
console.log("Client coordinates:" + event.clientX + "," + event.clientY);
})
script>
因为这些值不表示鼠标在页面上的位置,所以它们并不包含页面的滚动距离。
通过事件对象的 pageX 和 pageY 属性,可以获得事件是在页面中什么位置发生的,即鼠标光标在页面中的位置,因为坐标是从页面本身的左边和顶边计算得出的:
<div id="myDiv">点我div>
<script type="text/javascript" src="EventUtil.js">script>
<script type="text/javascript">
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function (event) {
event = EventUtil.getEvent(event);
console.log("Page coordinates:" + event.pageX + "," + event.pageY);
})
script>
页面没有滚动的情况下,pageX 等于 clientX,pageY 等于 clientY。
IE8 及早期版本不支持事件对象上的页面坐标,但可以通过客户区坐标和滚动信息计算出来。这需要用到 document.body(混杂)或 document.documentElement(标准)中的 scrollLeft 和 scrollTop 属性:
这是鼠标事件发生时,相对于整个电脑屏幕的位置:
<script type="text/javascript">
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function (event) {
event = EventUtil.getEvent(event);
console.log("Screen coordinates:" + event.screenX + "," + event.screenY);
})
script>
配合这些修改键——Shift、Ctrl、Alt 和 Meta(Windows 中是 Windows 键,苹果中是 Cmd 键),经常被用来修改鼠标事件的行为。DOM 规定了 shiftKey、ctrlKey、altKey、metaKey,它们都是布尔值,如果相应的键被按下,它的值变为 true。当某个鼠标事件发生时,通过检测这些属性就能确定用户是否同时按下了其中的键:
这里同时检测了 readyState 的两个状态,并在调用过一次事件处理程序之后,就将其移除咯。
它会在 URL(# 后面的所有字符串) 的参数列表发生变化时触发。
要把这个事件添加给 window 对象。它的 event 对象包含 oldURL 和 newURL,即参数变化前后的完整的 URL:
<script type="text/javascript">
EventUtil.addHandler(window, "haschange", function (event) {
console.log("Old URL: " + event.oldURL + "\nNew URL:" + event.newURL); console.log("Current hash:" + location.hash);
})
script>
IE8+、Firefox 3.6+、Safari 5+、Chrome 和 Opera 10.6+ 都支持这个事件,但只有 Firefox 6+、Chrome 和 Opera 支持 oldURL 和 newURL,所以最好使用 location 对象来确定当前的参数列表:
<script type="text/javascript">
EventUtil.addHandler(window, "haschange", function (event) {
console.log("Current hash:" + location.hash);
})
script>
可以这样检测浏览器是否支持 hashchange 事件:
var isSupported = ("onhashchange" in window) && (document.documentMode == undefined ||
document.documentMode > 7);
console.log(isSupported);
因为 IE8 是在 IE7 文档模式下运行的,所以即使功能无效它也会返回 true,所以上面的检测必须针对这一情况进行特殊处理。