Internet Explorer的事件模型

  除了上节所介绍的事件模型外,不同浏览器还有自身所独有的事件机制,例如,Internet Explorer就包含了不少独有的事件特性,这些事件特性包括Internet Explorer自己的事件绑定机制,以及独有的事件传播机制等。

使用script for绑定

  Internet Explorer还支持两种自己独有的事件绑定方法。这两种方法都不需要在HTML元素中增加额外的属性,下面依次介绍Internet Explorer中的事件绑定方法。
  在Internet Explorer 4.0以及更新的版本中,Microsoft扩展了<script.../>元素,可以将它包含的脚本语句和某个元素的某个事件类型进行绑定,完成绑定的两个属性是for和event。
  for属性的值必须是HTML文档中某个元素的id属性值,该属性值唯一地标识了该HTML元素。event属性值是该元素所支持的事件名称,如onmouseover、onclick等。一旦为该script标签指定了这两个属性,就表明该标签内的所有脚本绑定了该元素的对应事件。在这种绑定机制下,事件处理的脚本语句并不在函数中,而是在<script.../>元素内。

注意

  值得注意的是,这种绑定方式仅支持Internet Explorer 4.0以及更新的版本,其他浏览器则没有实现这个特殊的<script.../>元素。因此应该尽量避免使用这种绑定方式,如果客户端的浏览器不是Internet Explorer 4.0或更新的版本,将不可避免地引起脚本错误。

使用attachEvent方法执行绑定

  在W3C指定标准的事件模型之前,attachEvent()方法已经被实现了,并可被用于Internet Explorer 5.0以及更新的版本,该方法可以作用于浏览器中的每个HTML元素。
  attachEvent()方法的语法格式如下:
  domObject.attachEvent("eventName",funtionReference);
  与attachEvent()方法对应的是detachEvent()方法,该方法用于删除一个事件处理器,其语法格式如下:
  domObject.detachEvent("eventName",funtionReference);

例子
<!DOCTYPE html>  
<html>  
<head>  
    <meta http-equiv="Content-Type" content="text/html; charset=GBK" />
    <title> 使用attachEvent绑定事件处理函数 </title>
</head>  
<body>  
    <input type="button" id="bn1" name="bn1" value="单击我" />
    <script type="text/javascript">
    var test = function()
    {
        alert("单击按钮");
    }
    var haha = function()
    {
        alert("haha函数也被触发");
    }
    // 使用attachEvent绑定事件处理函数
    document.getElementById("bn1")
        .attachEvent("onclick" , test);
    // 使用attachEvent绑定事件处理函数
    document.getElementById("bn1")
        .attachEvent("onclick" , haha);
</script>  
</body>  
</html>  
注意

  这种事件绑定机制只是Internet Explorer所提出的事件绑定机制,并不是W3C制定的行业规范,其他浏览器暂不支持这种事件绑定机制,目前还有Opera支持这种事件绑定机制。

访问事件对象

  Internet Explorer中的事件对象是一个隐式可用的全局对象:event,当一个事件在浏览器中发生时,浏览器创建一个隐式可用的事件对象,JavaScript脚本通过event就可访问该对象。
  Internet Explorer中的事件对象有如下常用的属性。
  ➢ type:返回发生的事件类型,例如"click"等。
  ➢ srcElement:返回发生事件的HTML元素。
  ➢ clientX:返回发生鼠标事件在页面中的X坐标。
  ➢ clientY:返回发生鼠标事件在页面中的Y坐标。
  ➢ offsetX:返回发生鼠标事件位置相对于事件源的X坐标。
  ➢ offsetY:返回发生鼠标事件位置相对于事件源的Y坐标。
  ➢ button:对于鼠标事件有效,返回发生鼠标事件时所用的鼠标键。
  ➢ keyCode:对于键盘事件有效,返回发生键盘事件时所用的键盘键。
  ➢ altKey:返回boolean值,用以确定事件发生时是否按下了Alt组合键。
  ➢ ctrlKey:返回boolean值,用以确定事件发生时是否按下了Ctrl组合键。
  ➢ shiftKey:返回boolean值,用以确定事件发生时是否按下了Shift组合键。
  ➢ cancelBubble:阻止事件冒泡。关于事件传播,请看15.3.3节内容。
  ➢ returnValue:返回事件处理函数的返回值。在整个事件传播链中,事件处理函数可以改变该值,当该值被设为false时,该事件的默认行为被取消。
  ➢ fromElement:对mouseover和mouseout两个事件有效,用于返回鼠标移出的HTML元素。
  ➢ toElement:对mouseover和mouseout两个事件有效,用于返回鼠标移入的HTML元素。

例子
<!DOCTYPE html>  
<html>  
<head>  
    <meta http-equiv="Content-Type" content="text/html; charset=GBK" />
    <title> JavaScript树 </title>
    <style type="text/css">
    /* 控制根节点的CSS样式定义 */
    .outline {
        font-size: 9pt; 
        margin-left: 15pt; 
        text-indent: -28pt; 
        cursor: hand;
        text-decoration: none
    }
    /* 控制第一级子节点的CSS样式定义 */
    .outline1 {
        font-size: 9pt;
        margin-left: 24pt;
        text-indent: -36pt; 
        cursor: hand;
        text-decoration: none
    }
    /* 控制第二级子节点的CSS样式定义 */
    .outline11 {
        font-size: 9pt; 
        margin-left: 38pt; 
        text-indent: -50pt; 
        cursor: hand;
        text-decoration: none
    }
    /* 控制根节点下叶子节点的CSS样式定义 */
    .passage0 {
        font-size: 9pt; 
        margin-left: 15pt; 
        text-indent: -28pt;
        text-decoration: none
    }
    /* 控制第一级节点下叶子节点的CSS样式定义 */
    .passage1 {
        font-size: 9pt; 
        margin-left: 24pt; 
        text-indent: -36pt; 
        text-decoration: none
    }
    /* 控制第二级节点下叶子节点的CSS样式定义 */
    .passage11 {
        font-size: 9pt; 
        margin-left: 38pt; 
        text-indent: -50pt; 
        text-decoration: none
    }
    </style>
    <script type="text/javascript" src="tree.js">
    </script>
</head>  
<body>  
<div id="root" class="outline">  
    <img id="rootImage" class="outline" alt="rootImage"
        src="image/plus.gif" />我的电脑</div>
<div id="rootDetails" style="display:none">  
    <div id="child1" class="outline1">
        <img id="child1Image" class="outline1" alt="child1Image"
            src="image/plus.gif" />本地磁盘 C:</div>
    <div id="child1Details" style="display: none">
        <div class="passage11">
            <img class="passage11" src="image/passage.gif" />文件一</div>
        <div class="passage11">
            <img class="passage11" src="image/passage.gif" />文件二</div>
    </div>
    <div id="child2" class="outline1">
        <img id="child2Image" class="outline1" alt="child2Image"
            src="image/plus.gif" />本地磁盘 D:</div>
    <div id="child2Details" style="display: none">
        <div class="passage11">
            <img class="passage11" src="image/passage.gif"/>文件三</div>
        <div class="passage11">
            <img class="passage11" src="image/passage.gif"/>文件四</div>
    </div>
    <div id="child3" class="outline1">
        <img id="child3Image" class="outline1" alt="child3Image"
            src="image/plus.gif" />本地磁盘 E:</div>
    <div id="child3Details" style="display: none">
        <div class="passage11">
            <img class="passage11" src="image/passage.gif" />文件五</div>
        <div class="passage11">
            <img class="passage11" src="image/passage.gif" />文件六</div>
    </div>
    <div class="passage1">
        <img class="passage1" src="image/passage.gif" />文件七</div>
</div>  
</body>  
</html>  
tree.js
var clickHandler = function()  
{
    // 定义需要操作的HTML元素id
    var targetId;
    // 定义需要被操作的HTML元素
    var targetElement;
    // 定义触发事件的事件源(其中event是隐式可用的全局对象)
    var srcElement = event.srcElement;
    // 根据其className属性值判断它不是叶子节点,即该节点可以展开
    if(srcElement.className.substr(0,7) == "outline")
    {
        // 如果事件源是树节点前的图片
        if(srcElement.id.indexOf("Image") > 0)
        {
            // 获取该节点对应<div.../>元素的id
            targetId = srcElement.id.substring(0
                , srcElement.id.length - 5) + "Details";
        }
        // 如果事件源是树节点所在的<div.../>元素
        else
        {
            // 获取该节点对应<div.../>元素的id
            targetId = srcElement.id + "Details";
        }
        // 找到对应的<div.../>元素
        targetElement = document.getElementById(targetId);
        // 如果targetElement对象存在
        if(targetElement)
        {
            // 如果该<div.../>元素处于“隐藏”状态
            if (targetElement.style.display == "none")
            {
                // 显示该<div.../>元素
                targetElement.style.display = "";
            }
            else
            {
                // 否则,隐藏该<div.../>元素
                targetElement.style.display = "none";
            }
        }
        // 如果事件源是树节点前的图片
        if (srcElement.id.indexOf("Image") > 0)
        {
            // 获取该节点前的<img.../>元素的id
            targetId = srcElement.id;
        }
        // 如果事件源是树节点所在的<div.../>元素
        else
        {
            // 获取该节点前的<img.../>元素的id
            targetId = srcElement.id + "Image";
        }
        // 找到对应的<img.../>元素
        targetElement = document.getElementById(targetId);
        // 如果该<img.../>元素中显示的图片是“加号”图片
        if (targetElement.src.indexOf("plus") >= 0)
        {
            // 将<img.../>的“加号”图片换为“减号”图片
            targetElement.src = "image/minus.gif";
        }
        else
        {
            // 否则,将<img.../>的“减号”图片换为“加号”图片
            targetElement.src = "image/plus.gif";
        }
    }
}
//为页面文档的onclick事件绑定事件处理函数
document.onclick = clickHandler;  

  前面介绍的是将事件处理器绑定到DOM对象时获取事件的方式,如果绑定到HTML元素属性,则还有另一种绑定方式:由于绑定到HTML元素属性时可以传入参数,因此我们可以将event对象作为参数传入。

例子
<!DOCTYPE html>  
<html>  
<head>  
    <meta http-equiv="Content-Type" content="text/html; charset=GBK" />
    <title> Internet Explorer事件绑定 </title>
</head>  
<body>  
    <!-- 绑定事件处理器时,将event作为参数传入 -->
    <button onclick="clickHandler(event);">按钮</button>
    <script type="text/javascript">
        var clickHandler = function(evt)
        {
            // evt参数由系统传入,evt可访问事件对象
            alert(evt.srcElement.innerHTML);
        }
    </script>
</body>  
</html>  

注:本博客内容节选自李刚编著的疯狂HTML 5/CSS 3/JavaScript讲义 ,详细内容请参阅书籍。