陈童的博客's Archivers

From everyinch on 2014-01-29 13:34:35

ADS4.5 响应用户操作和事件——跨浏览器的事件属性和方法

DOM2级事件对象的继承关系如下图所示:
<img src="http://www.everyinch.net/wp-content/uploads/2014/01/blog_dom2Event.jpg" alt="blog_dom2Event" width="500" height="222" class="alignnone size-full wp-image-4760" />
下面看一看Event和MouseEvent对象的属性,并介绍通过这些属性可以获得哪些信息。

1. DOM2事件规范中的Event对象

事件对象中包含着用于控制事件流和目标对象的方法和属性。包括:
□ bubbles:布尔值,表示是否是冒泡阶段
□ cancelable:布尔值,表示事件是否具有可以取消的默认动作
□ currentTarget:当前正在处理的DOM元素
□ target:最早调用事件序列的对象(EventTarget对象的实例)
□ timestamp:DOMTimeStamp对象,用来确定创建事件后的毫秒数
□ type:包含事件名称(例如click)的字符串
□ eventPhase:表示处于事件流的阶段,使用1-3的整数来表示,也可以使用Event常量CAPTURE_PHASE、AT_TARGET和BUBBLING_PHASE。如下所示:
[code lang="js"]
function eventListener(W3CEvent) {
switch(W3CEvent.eventPhase) {
case Event.CAPTURING_PHASE:
//code to run if in the capturing phase
break;
case Event.AT_TARGET:
//code to run if this is the target
break;
case Event.BUBBLING_PHASE:
//code to run if in the bubbling phase
break;
}
}
[/code]
还可以根据事件的阶段使用target或currentTarget属性:
[code lang="js"]
function eventListener(W3CEvent) {
window.open(W3CEvent.currentTarget.href);
W3CEvent.preventDefault();
}
var anchor = document.getElementById('example');
anchor.addEventListener('click',eventListener,false);
[/code]
W3C也定义了下列Event对象的方法:
□ initEvent(eventType,canBubble,cancelable):初始化通过document.createEvent('Event')方法创建的事件对象
□ preventDefalt():取消对象的默认动作
□ stopPropagation():停止事件流的进一步执行

2. DOM2事件规范定义的MouseEvent对象

对于所有的W3C DOM鼠标事件而言,传递到事件侦听器中的事件对象都是MouseEvent对象的实例。MouseEvent对象的属性如下:
□ altKey、ctrlKey和shiftKey:布尔值,表示是否按住Alt、Ctrl或Shift键
□ button:表示鼠标键的整数值。0表示鼠标左键,1表示鼠标中键(如果有),2表示鼠标右键。例如:
[code lang="js"]
if(W3CEvent.button==0) {
// 单击左键的代码
}
[/code]
或者使用常量:
[code lang="js"]
if(W3CEvent.button==MouseEvent.BUTTON_LEFT) {
// 单击左键的代码
}
[/code]
□ clientX和clientY:表示事件发生位置相对于浏览器窗口的水平和垂直坐标。例如:
[code lang="js"]
document.addEventListener('click',function(W3CEvent) {
alert('client: (' + W3CEvent.clientX + ',' + W3CEvent.clientY + ')');
},false);
[/code]
下图展示了滚动网页前后clientX和clientY表示的位置:
<img src="http://www.everyinch.net/wp-content/uploads/2014/01/blog_clientXY.jpg" alt="blog_clientXY" width="550" height="210" class="alignnone size-full wp-image-4761" />
□ screenX和screenY:表示事件发生位置相对于屏幕的水平和垂直坐标。下图展示了screenX和screenY表示的位置:
<img src="http://www.everyinch.net/wp-content/uploads/2014/01/blog_screenXY.jpg" alt="blog_screenXY" width="550" height="344" class="alignnone size-full wp-image-4759" />
□ relatedTarget:引用与事件相关的“次要目标”。在多数情况下,这个属性值是null,但在mouseover事件中,它引用的是鼠标离开的前一个对象;同样,在mouseout事件中,它引用的是鼠标之前进入的那个对象。

3. 处理诸多浏览器不兼容问题

访问事件的目标元素:IE没有提供target和currentTarget属性,但却提供了srcElement属性。对于Safari而言,文本节点会代替包含它的元素节点变成事件的目标对象。要解决这些问题,添加自定义的ADS.getTarget()方法:
[code lang="js"]
/**
* 访问事件的目标元素
*/
function getTarget(eventObject) {
eventObject = eventObject || getEventObject(eventObject);
// 如果是W3C或MSIE模型
var target = eventObject.target || eventObject.scrElement;
// 如果是Safari,则将目标对象指定为文本节点的父元素
if(target.nodeType == ADS.node.TEXT_NODE) {
target = node.parentNode;
}
return target;

}
window['ADS']['getTarget'] = getTarget;
[/code]
通过这个方法可以取得给定事件的目标:
[code lang="js"]
ADS.addEvent(window, 'load', function() {
function eventListener(W3CEvent) {
//取得目标
var target = ADS.getTarget(W3CEvent);
window.open(target.href);
}
var anchor = document.getElementById('example');
addEvent(anchor, 'click', eventListener);
});
[/code]
确定单击了鼠标哪个键:W3C规定:
□ 0表示按下了左键
□ 1表示按下了中键
□ 2表示按下了右键
Microsoft的规定如下:
□ 0表示没有按下任何键
□ 1表示按下左键
□ 2表示按下右键
□ 3表示同时按下了左右键
□ 4表示按下了中键
□ 5表示同时按下了左中键
□ 6表示同时按下了右中键
□ 7表示同时按下了所有三个键
解决这个不兼容问题的方法是:检测事件具有toString()方法并且返回的是MouseEvent,那么考虑使用W3C的方式;否则如果仍然存在button属性,那就可以假设是IE了。现在添加自定义的ADS.getMouseButton()方法:
[code lang="js"]
/**
* 确定按下了鼠标哪个键
*/
function getMouseButton(eventObject) {
eventObject = eventObject || getEventObject(eventObject);
// 初始化一个对象变量
var buttons = {
'left':false,
'middle':false,
'right':false
};
// 检查eventObject对象的toString()方法的值
// W3C DOM对象有toString方法而且返回值为MouseEvent
if(eventObject.toString && eventObject.toString().indexOf('MouseEvent') != -1) {
// W3C方法
switch(eventObject.button) {
case 0: buttons.left = true; break;
case 1: buttons.middle = true; break;
case 2: buttons.right = true; break;
default: break;
}
} else if(eventObject.button) {
// MSIE方法
switch(eventObject.button) {
case 1: buttons.left = true; break;
case 2: buttons.right = true; break;
case 3:
buttons.left = true;
buttons.right = true;
break;
case 4: buttons.middle = true; break;
case 5:
buttons.left = true;
buttons.middle = true;
break;
case 6:
buttons.middle = true;
buttons.right = true;
break;
case 7:
buttons.left = true;
buttons.middle = true;
buttons.right = true;
break;
default: break;
}
} else {
return false;
}
return buttons;

}
window['ADS']['getMouseButton'] = getMouseButton;
[/code]
处理鼠标的位置:虽然W3C和IE都定义了clientX和clientY鼠标,但它们在确定滚动后的位移属性时却不相同。W3C使用document.documentElement.scrollTop,而IE则使用document.body.scrollTop。对于Safari而言,它把位置信息放在了事件的pageX和pageY属性中。下面的ADS.getPointerPositionInDocument()方法一并处理了这些情况:
[code lang="js"]
/**
* 取得鼠标指针在文档中的位置
*/
function getPointerPositionInDocument(eventObject) {
eventObject = eventObject || getEventObject(eventObject);
var x = eventObject.pageX || (eventObject.clientX +
(document.documentElement.scrollLeft || document.body.scrollLeft));
var y= eventObject.pageY || (eventObject.clientY +
(document.documentElement.scrollTop || document.body.scrollTop));
//相对于文档原点的坐标
return {'x':x,'y':y};
}
window['ADS']['getPointerPositionInDocument'] = getPointerPositionInDocument;
[/code]
有了ADS.getPointerPositionInDocument()方法,就可以通过mousemove事件让一个元素跟随鼠标指针移动:
[code lang="js"]
ADS.addEvent(window,'load',function() {

// 取得要移动的对象
var object = document.getElementById('follow');

// 绝对定位
object.style.position = 'absolute';

// 事件侦听器
function eventListener(W3CEvent) {
var pointer = ADS.getPointerPositionInDocument(W3CEvent);

// 相对于鼠标指针来定位对象
object.style.left = pointer.x + 'px';
object.style.top = pointer.y + 'px';

}
// 在document上注册事件侦听器
ADS.addEvent(document,'mousemove',eventListener);
});
[/code]
效果演示

4. 访问键盘命令

可以通过事件对象的keyCode属性取得按键的Unicode值。添加到ADS库中的ADS.getKeyPressed()方法,可以通过它取得按键代码及相关的ASCII值:
[code lang="js"]
/**
* 从事件对象中取得按键值
*/
function getKeyPressed(eventObject) {
eventObject = eventObject || getEventObject(eventObject);
var code = eventObject.keyCode;
var value = String.fromCharCode(code);
return {'code':code,'value':value};
}
window['ADS']['getKeyPressed'] = getKeyPressed;
[/code]
通过这个方法就可以确定在键盘事件中按下的键了。例如:
[code lang="js"]
ADS.addEvent(document, 'keydown', function(W3CEvent) {
var key = ADS.getKeyPressed(W3CEvent);
ADS.log.write(key.code + ':' + key.value);
});
[/code]

查看完整版本: ADS4.5 响应用户操作和事件——跨浏览器的事件属性和方法

Tags:


©陈童的博客