关于Mouse事件的一些测试

根据昨天在#javascript罗浮宫2群#与@可乐 同学的讨论,浏览器在处理鼠标右键的MosueEvent序列时存在一些不同,在此摘录并邀请大家讨论:

测试页面如下:

  <!DOCTYPE html>
  <html>
  <head>
  <meta charset="utf-8" />
      <title>Hello World</title>
  </head>
  <body>
      <div style="width: 400px; height: 400px; background: red;"></div>
      <script>
          var div = document.getElementsByTagName('div')[0];
          div.addEventListener('mousedown', function() { console.log('mousedown on div'); }, false);
          div.addEventListener('up', function() { console.log('mousedown on div'); }, false);
          div.addEventListener('click', function() { console.log('mousedown on div'); }, false);
          div.addEventListener('contextmenu', function() { console.log('mousedown on div'); }, false);
          document.addEventListener('mousedown', function() { console.log('mousedown on document'); }, false);
          document.addEventListener('up', function() { console.log('mousedown on document'); }, false);
          document.addEventListener('click', function() { console.log('mousedown on document'); }, false);
          document.addEventListener('contextmenu', function() { console.log('mousedown on document'); }, false);
      </script>
  </body>
  </html>
在红色的<div>元素上右键单击一次后,出现的事件顺序在各浏览器中如下:

Chrome 17:
mousedown on div
mousedown on document
mouseup on div
mouseup on document
contextmenu on div
contextmenu on document

Firefox 11:
mousedown on div
mousedown on document
mouseup on div
mouseup on document
click on document
contextmenu on div
contextmenu on document

IE 9:
mousedown on div 
mousedown on document 
mouseup on div 
mouseup on document 
contextmenu on div 
contextmenu on document 

可以看到,Chrome和IE行为相同,而Firefox会额外在document上触发一个click事件,且该事件不捕获(有使用useCapture参数测试)不冒泡。

如果给所有的事件处理函数加上preventDefault行为,则各浏览器中的结果如下:

Chrome 17:
mousedown on div
mousedown on document
mouseup on div
mouseup on document
contextmenu on div
contextmenu on document
不弹出菜单

Firefox 11:
mousedown on div
mousedown on document
mouseup on div
mouseup on document
click on document
不弹出菜单

IE 9:
mousedown on div 
mousedown on document 
mouseup on div 
mouseup on document 
contextmenu on div 
contextmenu on document 
不弹出菜单

同样Chrome和IE9有相同的结果,Firefox则会因为click事件中的preventDefault行为影响contextmenu事件的触发

根据DOM Event Level3(http://www.w3.org/TR/DOM-Level-3-Events/#event-type-click )中的描述:


  The default action of the click event type varies based on the proximal event target of the event and the value of the MouseEvent.button or MouseEvent.buttons attributes. Typical default actions of the click event type are as follows:

  Left click (MouseEvent.button value is 0, MouseEvent.buttons value is 1):
      If the proximal event target has associated activation behavior, the default action must be to execute that activation behavior (see Activation triggers and behavior).
      If the proximal event target is focusable, the default action must be to give that element document focus.

  Right click (MouseEvent.button value is 1, MouseEvent.buttons value is 2):
      The default action must be to provide a context menu of options related to that proximal event target.

  Middle click (MouseEvent.button value is 2, MouseEvent.buttons value is 4):
      If the proximal event target has associated activation behavior, the default action must be to execute that activation behavior in an alternate fashion (such as opening a link in a new tab or window).
      If the proximal event target has no associated activation behavior, the default action must be device- and user-defined, but when associated with a device wheel, is often to activate an alternate scrolling or panning mode.
可以有以下结论:


1. click事件的default action根据按键的不同有不同的行为,并且明确定义了右键(Right click)时的行为,因此认为鼠标右键应当能触发click事件。在这一点上,Firefox更靠近标准实现,但仅在document上触发一个不捕获不冒泡的事件,行为较为怪异。在关于右键与click事件的关系上,请大家提供更多的资料或讨论。

2. 鼠标右键click事件的default action是“提供contextmenu”,因此在click事件中使用preventDefault,会阻止contextmenu的出现,这一点所有浏览器一致。但是“不提供contextmenu”是否意味着同时“不触发contextmenu”事件,在这点上各浏览器理解不同,Chrome和IE都选择触发contextmenu但不显示菜单,这一点类似HTML标准中由tabindex引起不可聚焦元素变为可聚焦时(http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#focus )的相关行为(activation behavior which will fire a xxx event but does nothing)。但是Firefox选择同时阻止contextmenu事件的触发。在这两者之间哪一个正为准确,邀请大家讨论。

--------------------------------------------------------

Gray Zhang
Mail: otakustay@gmail.com
Blog: http://www.otakustay.com
Weibo: http://www.weibo.com/otakustay

Received on Friday, 16 March 2012 05:36:19 UTC