<input type="button" value="Click Me" onclick="try{showMessage();}catch(ex){}">
使用try catch捕获错误
try {
var dd = document.getElemedntById('dd')
} catch (ex) {
alert(123)
}
addEventListener(),最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程
try {
btn.addEventListener('click', function() {
alert(this.id)
}, false)
} catch (ex) {
btn.attachEvent('onclick', function() {
alert(123)
})
}
removeEventListener(),要使用命名函数才能移除
btnfn = function() {
alert(this.id)
}
btn.addEventListener('click', btnfn, false)
btn.removeEventListener('click',btnfn,false)
attachEvent()与detachEvent(),1、this作用域为window; 2、执行顺序由后往前;
btn.attachEvent('onclick',function(){
alert(this) //特别注意,这里是window
})
btn.attachEvent("onclick", function(){
alert("Clicked"); //弹2
});
btn.attachEvent("onclick", function(){
alert("Hello world!"); //弹1
});
兼容方法:
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
removeHandler: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
}
};
var handler = function() {
alert('abc')
}
EventUtil.addHandler(btn, 'click', handler)
EventUtil.removeHandler(btn, "click", handler);
事件对象
对象this 始终等于currentTarget 的值,而target 则只包含事件的实
际目标。如果直接将事件处理程序指定给了目标元素,则this、currentTarget 和target 包含相同
的值。来看下面的例子。
btn.onclick = function(event){
alert(event.currentTarget === this)
alert(event.target === this)
}
document.body.onclick = function(event) {
alert(event.currentTarget == document.body) //true
alert(this === document.body) //true
alert(event.target == document.getElementById('mybtn')) //true
}
使用event.type判断不同事件;
var handler = function(event) {
switch (event.type) {
case 'click':
alert('clicked')
break;
case 'mouseover':
alert('mouseovered')
break;
case 'mouseout':
alert('mouseouted');
break;
}
}
btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler;
btn.onclick = function(event) {
alert('clicked')
event.stopPropagation()
}
document.body.onclick = function(event) {
alert('body clicked')
}
IE下的事件;
所以不能认为this 会始终等于事件目标。故而,最好还是使用event.srcElement 比较保
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert(window.event.srcElement === this); //true
};
btn.attachEvent("onclick", function(event){
alert(event.srcElement === this); //false
});
cancelBubble 属性与DOM 中的stopPropagation()方法作用相同,都是用来停止事
件冒泡的。由于IE 不支持事件捕获,因而只能取消事件冒泡;但stopPropagatioin()可以同时取消
事件捕获和冒泡
所以综合起来的跨浏览器事件代码为:
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
getEvent: function(event) {
return event ? event : window.event;
},
getTarget: function(event) {
return event.target || event.srcElement;
},
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
removeHandler: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
stopPropagation: function(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
};
//使用
btn.onclick = function(event) {
event = EventUtil.getEvent(event);
};
btn.onclick = function(event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
};
var link = document.getElementById("myLink");
link.onclick = function(event) {
event = EventUtil.getEvent(event);
EventUtil.preventDefault(event);
};
var btn = document.getElementById("myBtn");
btn.onclick = function(event) {
alert("Clicked");
event = EventUtil.getEvent(event);
EventUtil.stopPropagation(event);
};
document.body.onclick = function(event) {
alert("Body clicked");
};
图片加载完后显示弹出
var image = document.getElementById('myimage')
EventUtil.addHandler(image,'load',function(event){
event = EventUtil.getEvent(event);
alert(EventUtil.getTarget(event).src);
})
EventUtil.addHandler(window,'load',function(){
var image = new Image();
EventUtil.addHandler(image,'load',function(event){
alert('Image Loaded')
})
image.src = 'smail.gif'
})
script外部地址加载完成
EventUtil.addHandler(window,'load',function(){
var _srcipt = document.createElement('script')
EventUtil.addHandler(_srcipt,'load',function(event){
alert('loaded')
})
_srcipt.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js'
document.body.appendChild(_srcipt)
})
css外部检测,低版本chrome/firefox可能不支持,未验证
EventUtil.addHandler(window, 'load', function() {
var _css = document.createElement('link')
_css.type = 'text/css'
_css.rel = 'stylesheet'
EventUtil.addHandler(_css, 'load', function(event) {
alert('loaded')
})
_css.href = 'https://assets-cdn.github.com/assets/frameworks-827a4e004aa05724993ea7616e4af53894825443811a270e2b9bce76e3453f19.css'
document.body.appendChild(_srcipt)
})
resize事件,推荐写法
EventUtil.addHandler(window, "resize", function(event) {
alert("Resized");
});
EventUtil.addHandler(window, "scroll", function(event) {
if (document.compatMode == "CSS1Compat") {
alert(document.documentElement.scrollTop);
} else {
alert(document.body.scrollTop);
}
});
焦点事件会在页面元素获得或失去焦点时触发。利用这些事件并与document.hasFocus()方法及
document.activeElement 属性配合,可以知晓用户在页面上的行踪。有以下6 个焦点事件。
blur:在元素失去焦点时触发。这个事件不会冒泡;所有浏览器都支持它。
DOMFocusIn:在元素获得焦点时触发。这个事件与HTML 事件focus 等价,但它冒泡。只有
Opera 支持这个事件。DOM3 级事件废弃了DOMFocusIn,选择了focusin。
DOMFocusOut:在元素失去焦点时触发。这个事件是HTML 事件blur 的通用版本。只有Opera
支持这个事件。DOM3 级事件废弃了DOMFocusOut,选择了focusout。
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。
当焦点从页面中的一个元素移动到另一个元素,会依次触发下列事件:
(1) focusout 在失去焦点的元素上触发;
(2) focusin 在获得焦点的元素上触发;
(3) blur 在失去焦点的元素上触发;
(4) DOMFocusOut 在失去焦点的元素上触发;
(5) focus 在获得焦点的元素上触发;
(6) DOMFocusIn 在获得焦点的元素上触发。
事件都不冒泡
var _mybtn = document.getElementById('mybtn')
EventUtil.addHandler(_mybtn, 'focus', function() { //获得
alert(1)
})
EventUtil.addHandler(_mybtn, 'blur', function() {//失去
alert(2)
})
EventUtil.addHandler(_mybtn, 'focusin', function() {//获得
alert(1)
})
EventUtil.addHandler(_mybtn, 'focusout', function() {//失去
alert(2)
})
鼠标与滚轮事件
click/dblclick/mouseenter/mouseleave/mousemove/mouseout/mouseover/mouseup/
执行顺序:
(1) mousedown
(2) mouseup
(3) click
(4) mouseup
(5) dblclick
可以使用类似下列代码取得鼠标事件的客户端坐标信息:
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function(event){
event = EventUtil.getEvent(event);
alert("Client coordinates: " + event.clientX + "," + event.clientY);
});
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function(event){
event = EventUtil.getEvent(event);
alert("Page coordinates: " + event.pageX + "," + event.pageY);
});
在页面没有滚动的情况下,pageX 和pageY 的值与clientX 和clientY 的值相等。
滚动情况下:page 一定大于 client
EventUtil.addHandler(document.body, "click", function(event) {
event = EventUtil.getEvent(event);
console.log("Page coordinates: " + event.pageX + "," + event.pageY);
});
EventUtil.addHandler(document.body, "click", function(event) {
event = EventUtil.getEvent(event);
console.log("client coordinates: " + event.clientX + "," + event.clientY);
});
IE8不支持page,所以可用client + scroll 相加计算出
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);
}
if (pageY === undefined) {
pageY = event.clientY + (document.body.scrollTop ||
document.documentElement.scrollTop);
}
alert("Page coordinates: " + pageX + "," + pageY);
});
鼠标相对于整个屏幕坐标位置,screenX 和 screenY
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function(event){
event = EventUtil.getEvent(event);
alert("Screen coordinates: " + event.screenX + "," + event.screenY);
});
虽然鼠标事件主要是使用鼠标来触发的,但在按下鼠标时键盘上的某些键的状态也可以影响到所要
采取的操作。这些修改键就是Shift、Ctrl、Alt 和Meta(在Windows 键盘中是Windows 键,在苹果机中
是Cmd 键),它们经常被用来修改鼠标事件的行为。DOM 为此规定了4 个属性,表示这些修改键的状
态:shiftKey、ctrlKey、altKey 和metaKey。这些属性中包含的都是布尔值,如果相应的键被按
下了,则值为true,否则值为false。当某个鼠标事件发生时,通过检测这几个属性就可以确定用户
是否同时按下了其中的键。来看下面的
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function(event) {
event = EventUtil.getEvent(event);
var keys = new Array();
if (event.shiftKey) {
keys.push("shift");
}
if (event.ctrlKey) {
keys.push("ctrl");
}
if (event.altKey) {
keys.push("alt");
}
if (event.metaKey) {
keys.push("meta");
}
alert("Keys: " + keys.join(","));
});
DOM通过event 对象的relatedTarget 属性提供了相关元素的信
只对于mouseover和mouseout 事件才包含值,其它值是null
IE8及之前版本不支持relatedTarget
mouseover -->IE 的fromElement
mouseout --》IE 的toElement
继续完善
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
getEvent: function(event) {
return event ? event : window.event;
},
getTarget: function(event) {
return event.target || event.srcElement;
},
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
removeHandler: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
stopPropagation: function(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
},
getRelatedTarget: function(event) {
if (event.relatedTarget) {
return event.relatedTarget;
} else if (event.toElement) {
return event.toElement;
} else if (event.fromElement) {
return event.fromElement;
} else {
return null;
}
}
};
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "mouseout", function(event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
var relatedTarget = EventUtil.getRelatedTarget(event);
alert("Moused out of " + target.tagName + " to " + relatedTarget.tagName);
//Moused out of DIV to BODY
鼠标按钮
DOM的button 属性可能有如下3 个值:0 表示主鼠标按钮,1 表示中间的鼠
标按钮(鼠标滚轮按钮),2 表示次鼠标按钮。在常规的设置中,主鼠标按钮就是鼠标左键,而次鼠标
按钮就是鼠标右
最常见的做法就是将IE 模型规范化为DOM 方式
添加getButton
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
getEvent: function(event) {
return event ? event : window.event;
},
getTarget: function(event) {
return event.target || event.srcElement;
},
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
removeHandler: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
stopPropagation: function(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
},
getRelatedTarget: function(event) {
if (event.relatedTarget) {
return event.relatedTarget;
} else if (event.toElement) {
return event.toElement;
} else if (event.fromElement) {
return event.fromElement;
} else {
return null;
}
},
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 2:
case 6:
return 2;
case 4:
return 1;
}
}
}
};
var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "mousedown", function(event) {
event = EventUtil.getEvent(event);
alert(EventUtil.getButton(event)); //左0 中1 右2
});
鼠标滚轮:
mousewheel 事件时显示wheelDelta 的值,
ff:支持:DOMMouseScroll
EventUtil.addHandler(document, "mousewheel", function(event){
event = EventUtil.getEvent(event);
console.log(event.wheelDelta); //上120,下-120
});
//ff
EventUtil.addHandler(window, "DOMMouseScroll", function(event) {
event = EventUtil.getEvent(event); // 上-3 下3
alert(event.detail);
});
整合添加:
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
getEvent: function(event) {
return event ? event : window.event;
},
getTarget: function(event) {
return event.target || event.srcElement;
},
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
removeHandler: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
stopPropagation: function(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
},
getRelatedTarget: function(event) {
if (event.relatedTarget) {
return event.relatedTarget;
} else if (event.toElement) {
return event.toElement;
} else if (event.fromElement) {
return event.fromElement;
} else {
return null;
}
},
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 2:
case 6:
return 2;
case 4:
return 1;
}
}
},
getWheelDelta: function(event) {
if (event.wheelDelta) {
return (event.wheelDelta);
} else {
return -event.detail * 40;
}
}
}
//使用
//handleMouseWheel()函数可以用作两个事件的处理程序(如果指定的事件不存在,则为该事件指定处
理程序的代码就会静默地失败)
function handleMouseWheel(event){
event = EventUtil.getEvent(event);
var delta = EventUtil.getWheelDelta(event);
alert(delta); //下-120,上120
}
EventUtil.addHandler(document, "mousewheel", handleMouseWheel);
EventUtil.addHandler(document, "DOMMouseScroll", handleMouseWheel);
键盘与文本
键盘事件:
keydown当用户按下键盘上的任意键时触发,而且如果按住不放的话,会重复触发此事件
keypress:当用户按下键盘上的字符键时触发,而且如果按住不放的话,会重复触发此事件。
按下Esc 键也会触发这个事件。Safari 3.1 之前的版本也会在用户按下非字符键时触发keypress
事件。
keyup:当用户释放键盘上的键时触发。
文本事件:textInput,对keypress补充
按下字符:keydown--》keypress【前两个是文本变化之前】--》keyup
连续按:连接触发:keydown--》keypress
按下非字符:keydown --》keyup
也有shiftKey、ctrlKey、altKey 和metaKey[非IE] 属性
键码
在发生keydown 和keyup 事件时,event 对象的keyCode 属性中会包含一个代码
var textbox = document.getElementById("myText");
EventUtil.addHandler(textbox, "keyup", function(event) {
event = EventUtil.getEvent(event);
alert(event.keyCode); //显示keyCode值
});
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
getEvent: function(event) {
return event ? event : window.event;
},
getTarget: function(event) {
return event.target || event.srcElement;
},
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
removeHandler: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
stopPropagation: function(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
},
getRelatedTarget: function(event) {
if (event.relatedTarget) {
return event.relatedTarget;
} else if (event.toElement) {
return event.toElement;
} else if (event.fromElement) {
return event.fromElement;
} else {
return null;
}
},
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 2:
case 6:
return 2;
case 4:
return 1;
}
}
},
getWheelDelta: function(event) {
if (event.wheelDelta) {
return (event.wheelDelta);
} else {
return -event.detail * 40;
}
},
getCharCode: function(event) {
if (typeof event.charCode == "number") {
return event.charCode;
} else {
return event.keyCode;
}
}
}
var textbox = document.getElementById("myText");
EventUtil.addHandler(textbox, "keypress", function(event) {
event = EventUtil.getEvent(event);
alert(EventUtil.getCharCode(event));//值出字符编码
});
之后可以使用String.fromCharCode(number),再转为正常字符;
所有非字符
特殊情况: ff o 分号键keyCode = 59 【ASCII分号编码】; ie safari分号键 = 186;【按键编码】
由于存在跨浏览器问题,因此本书不推荐使用key、keyIdentifier 或char。
textInput事件
替代keypress 的textInput 事件的行为稍有不同。
区别一:就是任何可以获得焦点的元素都可以触发keypress 事件,但只有可编辑区域才能触发textInput事件。
区别二:textInput 事件只会在用户按下能够输入实际字符的键时才会被触发,
而keypress事件则在按下那些能够影响文本显示的键时也会触发(例如退格键)。
由于textInput 事件主要考虑的是字符,因此它的event 对象中还包含一个data 属性,这个属
性的值就是用户输入的字符(而非字符编码)。换句话说,用户在没有按上档键的情况下按下了S 键,
data 的值就是"s",而如果在按住上档键时按下该键,data 的值就是"S"。
var textbox = document.getElementById("myText");
EventUtil.addHandler(textbox, "textInput", function(event){
event = EventUtil.getEvent(event);
alert(event.data); //按下什么输出什么
});
HTML5事件
- contextmenu 事件显示菜单,支持contextmenu 事件的浏览器有IE、Firefox、Safari、Chrome 和Opera 11+。
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 = "visible";
});
EventUtil.addHandler(document, "click", function(event) {
document.getElementById("myMenu").style.visibility = "hidden";
});
});
- beforeunload 事件,是为了让开发人员有可能在页面卸载前阻止这一操作,为了显示这个弹出对话框,必须将event.returnValue 的值设置为要显示给用户的字符串(对IE 及Fiefox 而言),同时作为函数的值返回
[
returnValue Boolean 读/写 默认值为true,但将其设置为false就可以取消事件的默认行为(与
DOM中的preventDefault()方法的作用相同)
]
EventUtil.addHandler(window, "beforeunload", function(event) {
event = EventUtil.getEvent(event);
var message = "I'm really going to miss you if you go.";
event.returnValue = message;
return message;
});
- DOMContentLoaded 事件 DOM加载完成后触发;
要处理DOMContentLoaded 事件,可以为document 或window 添加相应的事件处理程序(尽管
这个事件会冒泡到window,但它的目标实际上是document)。来看下面的例子。
注:这个事件始终都会在load 事件之前触发
EventUtil.addHandler(document, "DOMContentLoaded", function(event){
alert("Content loaded");
});
不支持的浏览器使用:
setTimeout(function(){
//在此添加事件处理程序
}, 0);
- readystatechange 事件
支持readystatechange 事件的每个对象都有一个readyState 属性
uninitialized(未初始化):对象存在但尚未初始化。
loading(正在加载):对象正在加载数据。
loaded(加载完毕):对象加载数据完成。
interactive(交互):可以操作对象了,但还没有完全加载。
complete(完成):对象已经加载完毕。
不支持则会跳过,所以一般readystatechange事件经常会少于4次;而readyState则总是不连续;
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");
}
});
对于上面的代码来说,当readystatechange 事件触发时,会检测document.readyState 的值,
看当前是否已经进入交互阶段或完成阶段。如果是,则移除相应的事件处理程序以免在其他阶段再执行。
注意,由于事件处理程序使用的是匿名函数,因此这里使用了arguments.callee 来引用该函数。然
后,会显示一个警告框,说明内容已经加载完毕。这样编写代码可以达到与使用DOMContentLoaded
十分相近的效
下面展示了一段加载外部JavaScript/css 文件的代码
//js
EventUtil.addHandler(window, "load", function() {
var script = document.createElement("script");
EventUtil.addHandler(script, "readystatechange", function(event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if (target.readyState == "loaded" || target.readyState == "complete") {
EventUtil.removeHandler(target, "readystatechange", arguments.callee);
alert("Script Loaded");
}
});
script.src = "example.js";
document.body.appendChild(script);
});
//css
EventUtil.addHandler(window, "load", function() {
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
EventUtil.addHandler(script, "readystatechange", function(event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if (target.readyState == "loaded" || target.readyState == "complete") {
EventUtil.removeHandler(target, "readystatechange", arguments.callee);
alert("CSS Loaded");
}
});
link.href = "example.css";
document.getElementsByTagName("head")[0].appendChild(link);
});
- pageshow 和pagehide 事件
(略)
- hashchange 事件
必须要把hashchange 事件处理程序添加给window 对象,然后URL 参数列表只要变化就会调用
它。此时的event 对象应该额外包含两个属性:oldURL 和newURL。这两个属性分别保存着参数列表
变化前后的完整URL。例如:
EventUtil.addHandler(window, "hashchange", function(event){
alert("Old URL: " + event.oldURL + "\nNew URL: " + event.newURL);
}); //前后变化,完整url
EventUtil.addHandler(window, "hashchange", function(event){
alert("Current hash: " + location.hash);
});//当前 #后字符
检测是否支持
var isSupported = ("onhashchange" in window) && (document.documentMode ===
undefined || document.documentMode > 7);
13.4.8 设备事件
- orientationchange 事件
苹果公司为移动Safari 中添加了orientationchange 事件,以便开发人员能够确定用户何时将设
备由横向查看模式切换为纵向查看模式。移动Safari 的window.orientation 属性中可能包含3 个值:
0 表示肖像模式,90 表示向左旋转的横向模式(“主屏幕”按钮在右侧),-90 表示向右旋转的横向模
式(“主屏幕”按钮在左侧)。相关文档中还提到一个值,即180 表示iPhone 头朝下;但这种模式至今
尚未得到支持。图13-10 展示了window.orientation 的每个值的含义
只要用户改变了设备的查看模式,就会触发orientationchange 事件。此时的event 对象不包
含任何有价值的信息,因为唯一相关的信息可以通过window.orientation 访问到。下面是使用这个
事件的典型示例
EventUtil.addHandler(window, "load", function(event) {
var div = document.getElementById("myDiv");
div.innerHTML = "Current orientation is " + window.orientation;
//改变时触发
EventUtil.addHandler(window, "orientationchange", function(event) {
div.innerHTML = "Current orientation is " + window.orientation;
});
});
//横屏
window.orientation == 90 || window.orientation == -90
//竖屏
window.orientation == 0 || window.orientation == 180
//粗略检测,并不准,ie都返回false
alert(document.implementation.hasFeature("orientationchange", "2.0"))
- deviceorientation 事件
- 事件的意图是告诉开发人员设备在空间中朝向哪儿,而不是如何移动;
设备在三维空间中是靠x、y 和z 轴来定位的 三个值都是0
x轴: 左 --》 右;
y轴: 下 --》 上;
z轴: 后 --》 前;
事件对象包含以下5 个属性。
alpha:在围绕z 轴旋转时(即左右旋转时),y 轴的度数差;是一个介于0 到360 之间的浮点数。
beta:在围绕x 轴旋转时(即前后旋转时),z 轴的度数差;是一个介于180 到180 之间的浮点数。
gamma:在围绕y 轴旋转时(即扭转设备时),z 轴的度数差;是一个介于90 到90 之间的浮点数。
absolute:布尔值,表示设备是否返回一个绝对值。
compassCalibrated:布尔值,表示设备的指南针是否校准过。
13.4.9 触摸与手势事件
touchstart/touchmove/touchend/touchcancel
每個event對象都有以下常見屬性;
bubbles、cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、ctrlKey 和metaKey。
touches:表示当前跟踪的触摸操作的Touch 对象的数组。
targetTouchs:特定于事件目标的Touch 对象的数组。
changeTouches:表示自上次触摸以来发生了什么改变的Touch 对象的数组。
每个Touch 对象包含下列属性。
clientX:触摸目标在视口中的x 坐标。
clientY:触摸目标在视口中的y 坐标。
identifier:标识触摸的唯一ID。
pageX:触摸目标在页面中的x 坐标。
pageY:触摸目标在页面中的y 坐标。
screenX:触摸目标在屏幕中的x 坐标。
screenY:触摸目标在屏幕中的y 坐标。
target:触摸的DOM 节点目标。
使用这些属性可以跟踪用户对屏幕的
function handleTouchEvent(event) {
if (event.touches.length == 1) {
var _output = document.getElementById('output')
switch (event.type) {
case 'touchstart':
_output.innerHTML = 'Touch started' + event.touches[0].clientX + ',' + event.touches[0].clientY
break;
case 'touchend':
_output.innerHTML += '<br> Touche ended' + event.changedTouches[0].clientX + ':' +
event.changedTouches[0].clientY + ';';
break;
case 'touchmove':
event.preventDefault();
_output.innerHTML += '<br> Touch move' +
event.changedTouches[0].clientX + ':' +
event.changedTouches[0].clientY + ';';
break;
}
}
}
EventUtil.addHandler(document, 'touchstart', handleTouchEvent)
EventUtil.addHandler(document, 'touchend', handleTouchEvent)
EventUtil.addHandler(document, 'touchmove', handleTouchEvent)
當touchstart發生: 觸摸信息輸出到<div>中 當touchmove發生:取消默認行為,阻止滾動,輸出變化信息
當touchend發生時:輸出有關觸摸操作信息,在touchend發生時:touches集合中就沒有任何信息,因為不存在活動觸摸操作,此時必須使用changeTouches集合
發生順序如下:
(1) touchstart
(2) mouseover
(3) mousemove(一次)
(4) mousedown
(5) mouseup
(6) click
(7) touchend
- 手势事件
當兩個手指觸摸時,就會產生手勢,手勢通常會改變顯示項大小,或旋轉顯示項,三個事件
gesturestart:当一个手指已经按在屏幕上而另一个手指又触摸屏幕时触发。
gesturechange:当触摸屏幕的任何一个手指的位置发生变化时触发。
gestureend:当任何一个手指从屏幕上面移开时触发。
当一个手指在屏幕时,触发touchstart
另一个手指放在屏幕,先触发gesturestart事件,随后触发该手指的touchstart
如果一个或两个手指在屏幕移动,触发gesturechange事件,但只要有一手指移开,触发gestureend事件,
最后再触发该手指的touchend事件;
每个event对象包含::
bubbles、cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、
ctrlKey 和metaKey、还有两个额外属性:rotation、scale
rotation: 表示手指变化引起的旋转角度, -值逆时针,+ 顺时针(该值从0开始)
scale: 表示两个手指距离变化情况,如内收缩会缩短距离,从1开始;
function handleTouchEvent(event) {
var _output = document.getElementById('output')
switch (event.type) {
case 'gesturestart':
_output.innerHTML = 'Gesture started rotation = ' + event.rotation + ', scale' + event.scale;
break;
case 'gestureend':
_output.innerHTML += '<br> Gesture end rotation = ' + event.rotation + ', scale' + event.scale;
break;
case 'gesturechange':
event.preventDefault();
_output.innerHTML += '<br> Gesture change rotation = ' + event.rotation + ', scale' + event.scale;
break;
}
}
EventUtil.addHandler(document, 'gesturestart', handleTouchEvent)
EventUtil.addHandler(document, 'gestureend', handleTouchEvent)
EventUtil.addHandler(document, 'gesturechange', handleTouchEvent)
13.5.1 事件委托
var list = document.getElementById('myLinks')
EventUtil.addHandler(list, 'click', function(event) { //父级绑定click
event = EventUtil.getEvent(event)
var target = EventUtil.getTarget(event)
switch (target.id) { //检测目标元素属性
case 'doSomething':
document.title = 'i cahnge the document is ttile'
break;
case 'goSomewhere':
location.href = 'http://www.x.com';
break;
case 'sayHi':
alert('hi')
break;
}
})
var btn = document.getElementById('myBtn')
btn.onclick = function(){
document.getElementById('myDiv').innerHTML = 'processing' //按钮被替换了,但click事件还在
}
//所以
var btn = document.getElementById('myBtn')
btn.onclick = function(){
btn.onclick = null; //先移除
document.getElementById('myDiv').innerHTML = 'processing' //按钮被替换了,但click事件还在
}
13.6.1 DOM中的事件模拟
- 模拟鼠标事件
创建新的鼠标事件对象并为其指定必要的信息,就可以模拟鼠标事件。创建鼠标事件对象的方法是
为createEvent()传入字符串"MouseEvents"。返回的对象有一个名为initMouseEvent()方法,
用于指定与该鼠标事件有关的信息。这个方法接收15 个参数,分别与鼠标事件中每个典型的属性一一
对应;这些参数的含义如下。
对应;这些参数的含义如下。
type(字符串):表示要触发的事件类型,例如"click"。
bubbles(布尔值):表示事件是否应该冒泡。为精确地模拟鼠标事件,应该把这个参数设置为
true。
cancelable(布尔值):表示事件是否可以取消。为精确地模拟鼠标事件,应该把这个参数设
置为true。
view(AbstractView):与事件关联的视图。这个参数几乎总是要设置为document.defaultView。
detail(整数):与事件有关的详细信息。这个值一般只有事件处理程序使用,但通常都设置为0。
screenX(整数):事件相对于屏幕的X 坐标。
screenY(整数):事件相对于屏幕的Y 坐标。
clientX(整数):事件相对于视口的X 坐标。
clientY(整数):事件想对于视口的Y 坐标。
ctrlKey(布尔值):表示是否按下了Ctrl 键。默认值为false。
altKey(布尔值):表示是否按下了Alt 键。默认值为false。
shiftKey(布尔值):表示是否按下了Shift 键。默认值为false。
metaKey(布尔值):表示是否按下了Meta 键。默认值为false。
button(整数):表示按下了哪一个鼠标键。默认值为0。
relatedTarget(对象):表示与事件相关的对象。这个参数只在模拟mouseover 或mouseout
时使用。
var btn = document.getElementById('myBtn')
//创建事件对象
var event = document.createEvent('mouseEvents')
//初始化
event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0,
false, false, false, false, 0, null);
//触发
btn.dispatchEvent(event)
- 模拟键盘事件
一、DOM3 级规定,调用createEvent()并传入"KeyboardEvent"就可以创建一个键盘事件。返回的
事件对象会包含一个initKeyEvent()方法,这个方法接收下列参数
type(字符串):表示要触发的事件类型,如"keydown"。
bubbles(布尔值):表示事件是否应该冒泡。为精确模拟鼠标事件,应该设置为true。
cancelable(布尔值):表示事件是否可以取消。为精确模拟鼠标事件,应该设置为true。
view (AbstractView ):与事件关联的视图。这个参数几乎总是要设置为document.
defaultView。
key(布尔值):表示按下的键的键码。
location(整数):表示按下了哪里的键。0 表示默认的主键盘,1 表示左,2 表示右,3 表示
数字键盘,4 表示移动设备(即虚拟键盘),5 表示手柄。
modifiers(字符串):空格分隔的修改键列表,如"Shift"。
repeat(整数):在一行中按了这个键多少次。
DOM3级不提倡使用keypress 事件,因此只能利用这种技术来模拟keydown 和keyup 事件。
var textbox = document.getElementById("myTextbox"),
event;
//以DOM3 级方式创建事件对象
if (document.implementation.hasFeature("KeyboardEvents", "3.0")) {
event = document.createEvent("KeyboardEvent");
//初始化事件对象
event.initKeyboardEvent("keydown", true, true, document.defaultView, "a", 0, "Shift", 0);
}
//触发事件
textbox.dispatchEvent(event);
这个例子模拟的是按住Shift 的同时又按下A 键。在使用document.createEvent
("KeyboardEvent")之前,应该先检测浏览器是否支持DOM3 级事件;其他浏览器返回一个非标准的
KeyboardEvent 对象。
二、在Firefox 中,调用createEvent()并传入"KeyEvents"就可以创建一个键盘事件。返回的事件
对象会包含一个initKeyEvent()方法,这个方法接受下列10 个参数。
type(字符串):表示要触发的事件类型,如"keydown"。
bubbles(布尔值):表示事件是否应该冒泡。为精确模拟鼠标事件,应该设置为true。
cancelable(布尔值):表示事件是否可以取消。为精确模拟鼠标事件,应该设置为true。
view(AbstractView):与事件关联的视图。这个参数几乎总是要设置为document.default-
View。
ctrlKey(布尔值):表示是否按下了Ctrl 键。默认值为false。
altKey(布尔值):表示是否按下了Alt 键。默认值为false。
shiftKey(布尔值):表示是否按下了Shift 键。默认值为false。
metaKey(布尔值):表示是否按下了Meta 键。默认值为false。
keyCode(整数):被按下或释放的键的键码。这个参数对keydown 和keyup 事件有用,默认
值为0。
charCode(整数):通过按键生成的字符的ASCII 编码。这个参数对keypress 事件有用,默
认值为0。
//只适用于Firefox
var textbox = document.getElementById("myTextbox")
//创建事件对象
var event = document.createEvent("KeyEvents");
//初始化事件对象
event.initKeyEvent("keypress", true, true, document.defaultView, false, false,
false, false, 65, 65);
//触发事件
textbox.dispatchEvent(event);
三、其它浏览器
首先创建了一个通用事件,然后调用initEvent()对其进行初始化,最后又为其添加了
键盘事件的具体信息。在此必须要使用通用事
var textbox = document.getElementById("myTextbox");
//创建事件对象
var event = document.createEvent("Events");
//初始化事件对象
event.initEvent(type, bubbles, cancelable);
event.view = document.defaultView;
event.altKey = false;
event.ctrlKey = false;
event.shiftKey = false;
event.metaKey = false;
event.keyCode = 65;
event.charCode = 65;
//触发事件
textbox.dispatchEvent(event);
- 模拟其他事件
模拟变动事件, 可以使用createEvent("MutationEvents") 创建一个包含
initMutationEvent() 方法的变动事件对象。这个方法接受的参数包括: type 、bubbles 、
cancelable、relatedNode、preValue、newValue、attrName 和attrChange。下面来看一个模
拟变动事件的例子。
var event = document.createEvent("MutationEvents");
event.initMutationEvent("DOMNodeInserted", true, false, someNode, "","","",0);
targ et.dispatchEvent(event);
以上代码模拟了DOMNodeInserted
- 自定义DOM 事件
创建新的自定义事件,可以调用createEvent("CustomEvent")。返回的对象有一个名为initCustomEvent()的方法
var div = document.getElementById("myDiv"),
event;
EventUtil.addHandler(div, "myevent", function(event) {
alert("DIV: " + event.detail);
});
EventUtil.addHandler(document, "myevent", function(event) {
alert("DOCUMENT: " + event.detail);
});
if (document.implementation.hasFeature("CustomEvents", "3.0")) {
event = document.createEvent("CustomEvent");
event.initCustomEvent("myevent", true, false, "Hello world!");
div.dispatchEvent(event);
}
创建了一个冒泡事件"myevent"。而event.detail 的值被设置成了一个简单的字符串,
然后在<div>元素和document 上侦听这个事件。因为initCustomEvent()方法已经指定这个事件应
该冒泡,所以浏览器会负责将事件向上冒泡到document。
支持自定义DOM事件的浏览器有IE9+和Firefox 6+。
13.6.2 IE中的事件模拟
IE8之前的版本
思路相似:先创建event 对象,然后为其指定相应的信息,然后再使用该对象来触发事件
调用document.createEventObject()方法可以在IE 中创建event 对象。但与DOM方式不同的是,这个方法不接受参数,结果会返回一个通用的event 对象
最后一步就是在目标上调用fireEvent()方法
fireEvent(事件处理程序的名称,event对象)
在调用fireEvent()方法时,会自动为event 对象添加srcElement 和type 属性
其他属性则都是必须通过手工添加的。换句话说,模拟任
何IE 支持的事件都采用相同的模式。例如,下面的代码模拟了在一个按钮上触发click 事件过程
var btn = document.getElementById("myBtn");
//创建事件对象
var event = document.createEventObject();
//初始化事件对象
event.screenX = 100;
event.screenY = 0;
event.clientX = 0;
event.clientY = 0;
event.ctrlKey = false;
event.altKey = false;
event.shiftKey = false;
event.button = 0;
//触发事件
btn.fireEvent("onclick", event);
//触发keypress事件
var textbox = document.getElementById("myTextbox");
//创建事件对象
var event = document.createEventObject();
//初始化事件对象
event.altKey = false;
event.ctrlKey = false;
event.shiftKey = false;
event.keyCode = 65;
//触发事件
textbox.fireEvent("onkeypress", event);
评论已关闭