1关于事件对象
ie:事件对象是window对象的一个属性event
dom:event对象是作为唯一参数传递给事件处理函数。arguments[0]
2关于IE与DOM事件兼容性的总结(参考javascript高级程序设计)
DOM属性/方法 |
IE属性/方法 |
altKey |
altKey |
bubbles |
- |
button |
button |
cancelBubble |
cancelBubble |
charCode |
keyCode |
clientX |
clientX |
clientY |
clientY |
ctrlKey |
ctrlKey |
currentTarget |
- |
detail |
- |
eventPhase |
- |
isChar |
- |
keyCode |
keyCode |
metaKey |
- |
pageX |
clientX+document.body.scrollLeft |
pageY |
clientY+document.body.scrollTop |
preventDefault() |
returnValue = false |
relateTarget |
fromElement/toElement |
screenX |
screenX |
screenY |
screenY |
shiftKey |
shiftKey |
stopPropagation() |
cancelBubble = true |
target |
srcElement |
timeStamp |
- |
type |
type |
具体的属性和方法意思我就不写清楚了,有不太明白的可以baidu、google一下~
3关于跨平台事件(针对第二点各个属性在ie和ff下的不同)
在这里javascript高级程序设计一书总结了一个容器对象,可以方便的解决事件兼容性问题。
具体如下:
EventUtil
var EventUtil = new Object();
EventUtil.addEventHandler = function (oTarget, sEventType, fnHandler) {
if (oTarget.addEventListener) {
oTarget.addEventListener(sEventType, fnHandler, false);
} else if (oTarget.attachEvent) {
oTarget.attachEvent("on" + sEventType, fnHandler);
} else {
oTarget["on" + sEventType] = fnHandler;
}
};
EventUtil.removeEventHandler = function (oTarget, sEventType, fnHandler) {
if (oTarget.removeEventListener) {
oTarget.removeEventListener(sEventType, fnHandler, false);
} else if (oTarget.detachEvent) {
oTarget.detachEvent("on" + sEventType, fnHandler);
} else {
oTarget["on" + sEventType] = null;
}
};
EventUtil.formatEvent = function (oEvent) {
if (isIE && isWin) {
oEvent.charCode = (oEvent.type == "keypress") ? oEvent.keyCode : 0;
oEvent.eventPhase = 2;
oEvent.isChar = (oEvent.charCode > 0);
oEvent.pageX = oEvent.clientX + document.body.scrollLeft;
oEvent.pageY = oEvent.clientY + document.body.scrollTop;
oEvent.preventDefault = function () {
this.returnValue = false;
};
if (oEvent.type == "mouseout") {
oEvent.relatedTarget = oEvent.toElement;
} else if (oEvent.type == "mouseover") {
oEvent.relatedTarget = oEvent.fromElement;
}
oEvent.stopPropagation = function () {
this.cancelBubble = true;
};
oEvent.target = oEvent.srcElement;
oEvent.time = (new Date).getTime();
}
return oEvent;
};
EventUtil.getEvent = function() {
if (window.event) {
return this.formatEvent(window.event);
} else {
return EventUtil.getEvent.caller.arguments[0];
}
};
4里面会用到判断浏览器是什么牌子的另一个脚本(detect.js)
具体代码如下:
detect.js
var sUserAgent = navigator.userAgent;
var fAppVersion = parseFloat(navigator.appVersion);
function compareVersions(sVersion1, sVersion2) {
var aVersion1 = sVersion1.split(".");
var aVersion2 = sVersion2.split(".");
if (aVersion1.length > aVersion2.length) {
for (var i=0; i < aVersion1.length - aVersion2.length; i++) {
aVersion2.push("0");
}
} else if (aVersion1.length < aVersion2.length) {
for (var i=0; i < aVersion2.length - aVersion1.length; i++) {
aVersion1.push("0");
}
}
for (var i=0; i < aVersion1.length; i++) {
if (aVersion1[i] < aVersion2[i]) {
return -1;
} else if (aVersion1[i] > aVersion2[i]) {
return 1;
}
}
return 0;
}
var isOpera = sUserAgent.indexOf("Opera") > -1;
var isMinOpera4 = isMinOpera5 = isMinOpera6 = isMinOpera7 = isMinOpera7_5 = false;
if (isOpera) {
var fOperaVersion;
if(navigator.appName == "Opera") {
fOperaVersion = fAppVersion;
} else {
var reOperaVersion = new RegExp("Opera (\\d+\\.\\d+)");
reOperaVersion.test(sUserAgent);
fOperaVersion = parseFloat(RegExp["$1"]);
}
isMinOpera4 = fOperaVersion >= 4;
isMinOpera5 = fOperaVersion >= 5;
isMinOpera6 = fOperaVersion >= 6;
isMinOpera7 = fOperaVersion >= 7;
isMinOpera7_5 = fOperaVersion >= 7.5;
}
var isKHTML = sUserAgent.indexOf("KHTML") > -1
|| sUserAgent.indexOf("Konqueror") > -1
|| sUserAgent.indexOf("AppleWebKit") > -1;
var isMinSafari1 = isMinSafari1_2 = false;
var isMinKonq2_2 = isMinKonq3 = isMinKonq3_1 = isMinKonq3_2 = false;
if (isKHTML) {
isSafari = sUserAgent.indexOf("AppleWebKit") > -1;
isKonq = sUserAgent.indexOf("Konqueror") > -1;
if (isSafari) {
var reAppleWebKit = new RegExp("AppleWebKit\\/(\\d+(?:\\.\\d*)?)");
reAppleWebKit.test(sUserAgent);
var fAppleWebKitVersion = parseFloat(RegExp["$1"]);
isMinSafari1 = fAppleWebKitVersion >= 85;
isMinSafari1_2 = fAppleWebKitVersion >= 124;
} else if (isKonq) {
var reKonq = new RegExp("Konqueror\\/(\\d+(?:\\.\\d+(?:\\.\\d)?)?)");
reKonq.test(sUserAgent);
isMinKonq2_2 = compareVersions(RegExp["$1"], "2.2") >= 0;
isMinKonq3 = compareVersions(RegExp["$1"], "3.0") >= 0;
isMinKonq3_1 = compareVersions(RegExp["$1"], "3.1") >= 0;
isMinKonq3_2 = compareVersions(RegExp["$1"], "3.2") >= 0;
}
}
var isIE = sUserAgent.indexOf("compatible") > -1
&& sUserAgent.indexOf("MSIE") > -1
&& !isOpera;
var isMinIE4 = isMinIE5 = isMinIE5_5 = isMinIE6 = false;
if (isIE) {
var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
reIE.test(sUserAgent);
var fIEVersion = parseFloat(RegExp["$1"]);
isMinIE4 = fIEVersion >= 4;
isMinIE5 = fIEVersion >= 5;
isMinIE5_5 = fIEVersion >= 5.5;
isMinIE6 = fIEVersion >= 6.0;
}
var isMoz = sUserAgent.indexOf("Gecko") > -1
&& !isKHTML;
var isMinMoz1 = sMinMoz1_4 = isMinMoz1_5 = false;
if (isMoz) {
var reMoz = new RegExp("rv:(\\d+\\.\\d+(?:\\.\\d+)?)");
reMoz.test(sUserAgent);
isMinMoz1 = compareVersions(RegExp["$1"], "1.0") >= 0;
isMinMoz1_4 = compareVersions(RegExp["$1"], "1.4") >= 0;
isMinMoz1_5 = compareVersions(RegExp["$1"], "1.5") >= 0;
}
var isNS4 = !isIE && !isOpera && !isMoz && !isKHTML
&& (sUserAgent.indexOf("Mozilla") == 0)
&& (navigator.appName == "Netscape")
&& (fAppVersion >= 4.0 && fAppVersion < 5.0);
var isMinNS4 = isMinNS4_5 = isMinNS4_7 = isMinNS4_8 = false;
if (isNS4) {
isMinNS4 = true;
isMinNS4_5 = fAppVersion >= 4.5;
isMinNS4_7 = fAppVersion >= 4.7;
isMinNS4_8 = fAppVersion >= 4.8;
}
var isWin = (navigator.platform == "Win32") || (navigator.platform == "Windows");
var isMac = (navigator.platform == "Mac68K") || (navigator.platform == "MacPPC")
|| (navigator.platform == "Macintosh");
var isUnix = (navigator.platform == "X11") && !isWin && !isMac;
var isWin95 = isWin98 = isWinNT4 = isWin2K = isWinME = isWinXP = false;
var isMac68K = isMacPPC = false;
var isSunOS = isMinSunOS4 = isMinSunOS5 = isMinSunOS5_5 = false;
if (isWin) {
isWin95 = sUserAgent.indexOf("Win95") > -1
|| sUserAgent.indexOf("Windows 95") > -1;
isWin98 = sUserAgent.indexOf("Win98") > -1
|| sUserAgent.indexOf("Windows 98") > -1;
isWinME = sUserAgent.indexOf("Win 9x 4.90") > -1
|| sUserAgent.indexOf("Windows ME") > -1;
isWin2K = sUserAgent.indexOf("Windows NT 5.0") > -1
|| sUserAgent.indexOf("Windows 2000") > -1;
isWinXP = sUserAgent.indexOf("Windows NT 5.1") > -1
|| sUserAgent.indexOf("Windows XP") > -1;
isWinNT4 = sUserAgent.indexOf("WinNT") > -1
|| sUserAgent.indexOf("Windows NT") > -1
|| sUserAgent.indexOf("WinNT4.0") > -1
|| sUserAgent.indexOf("Windows NT 4.0") > -1
&& (!isWinME && !isWin2K && !isWinXP);
}
if (isMac) {
isMac68K = sUserAgent.indexOf("Mac_68000") > -1
|| sUserAgent.indexOf("68K") > -1;
isMacPPC = sUserAgent.indexOf("Mac_PowerPC") > -1
|| sUserAgent.indexOf("PPC") > -1;
}
if (isUnix) {
isSunOS = sUserAgent.indexOf("SunOS") > -1;
if (isSunOS) {
var reSunOS = new RegExp("SunOS (\\d+\\.\\d+(?:\\.\\d+)?)");
reSunOS.test(sUserAgent);
isMinSunOS4 = compareVersions(RegExp["$1"], "4.0") >= 0;
isMinSunOS5 = compareVersions(RegExp["$1"], "5.0") >= 0;
isMinSunOS5_5 = compareVersions(RegExp["$1"], "5.5") >= 0;
}
}
4相关测试代码。
test
<html>
<head>
<title>Mouse Events Example</title>
<script type="text/javascript" src="detect.js"></script>
<script type="text/javascript" src="eventutil.js"></script>
<script type="text/javascript">
EventUtil.addEventHandler(window, "load", function ()
{
var obj = document.getElementById("div1");
EventUtil.addEventHandler(obj,"click",handlee);
});
var handlee = function()
{
var obj = document.getElementById("txt1");
var eventobj = EventUtil.getEvent();
obj.value = eventobj.target.tagName;
obj.value += "\n"+eventobj.target.id;
};
</script>
</head>
<body>
<p>Use your mouse to click and double click the red square.</p>
<div style="width: 100px; height: 100px; background-color: red" id="div1"></div>
<p><textarea id="txt1" rows="15" cols="50"></textarea></p>
</body>
</html>
5在自己测试中遇到的两个问题。
1用addEventLisenter(dom)/attachEvent(ie)时如果针对的事件触发对象是window,
事件函数必须写为声明式的像这样function foo(){}
//错误的写法(变量式)ie会报语法错误
<script>
window.attachEvent("onload",foo);
var foo = function()
{
alert("loaded");
};
</script>
//正确的写法(声明式)
<script>
window.attachEvent("onload",foo);
function foo()
{
alert("loaded");
};
</script>
其他的页面元素则两者皆可。
问题二:关于同一对象连续使用attachEvent执行顺序的问题
猜猜会先执行那一个alert?
<html>
<head>
<script>
var app = function()
{
var obj = document.getElementById("mypp");
obj.attachEvent("onclick",foo1);
obj.attachEvent("onclick",foo2);
}
var foo1 = function()
{
alert("clicked!");
};
var foo2 = function()
{
alert("also clicked!");
};
</script>
</head>
<body onload="app()">
<p id="mypp">test</p>
</body>
</html>
答案是上面的代码会先执行第二个alert。
如果你觉得你的思维是正确的那么再看看下面的代码:
test2
<html>
<head>
<script>
var app = function()
{
var obj = document.getElementById("mypp");
obj.attachEvent("onclick",foo1);
obj.attachEvent("onclick",foo2);
obj.attachEvent("onclick",foo3);
obj.attachEvent("onclick",foo4);
obj.attachEvent("onclick",foo5);
obj.attachEvent("onclick",foo6);
obj.attachEvent("onclick",foo7);
}
var foo1 = function(){alert("1");};
var foo2 = function(){alert("2");};
var foo3 = function(){alert("3");};
var foo4 = function(){alert("4");};
var foo5 = function(){alert("5");};
var foo6 = function(){alert("6");};
var foo7 = function(){alert("7");};
</script>
</head>
<body onload="app()">
<p id="mypp">test</p>
</body>
</html>
一段关于此的英文解释:
When event fires on the object, the object's event handler is called before pDisp, the specified function. If you attach multiple functions to the same event on the same object, the functions are called in random order, immediately after the object's event handler is called.
引用网上一位高人说的:
并不是什么随机问题,你可以去研究研究哈希对象,这种对象插入新元素的时候并不是顺序插入的,而是根据计算所得的hash值而定的,但在取用这些对象的时间是按照一定的顺序取的,所以就会出现你这种所谓的乱序问题。我估计DHTML里的这些对象的事件处理函数存放及JS对象都是一个个哈希对象,都是key-value这种键值对的模式。
所以在使用上还是要慎重的,最好不要做依赖于顺序的设计。
Tag标签: javascript,事件,event