打印

SD9025: IE6 IE7 IE8 Opera 支持除 INPUT 和 BUTTON 元素以外的其他元素的 'click' 方法

作者:孙东国

标准参考

"click" 方法用于模拟一个鼠标点击事件,可应用于 "type" 属性值为 "button" "checkbox" "radio" "reset" "submit" 的 INPUT 元素上,其他元素的 "click" 方法规范中并没有提及。

关于 "click" 方法请参考 W3C DOM-Level-2 中 Interface HTMLInputElement 的描述。

问题描述

IE6 IE7 IE8 Opera 支持除 INPUT 和 BUTTON 元素以外的其他元素的 "click" 方法,这使得各浏览器对除 INPUT 和 BUTTON 元素以外的其他元素的 "click" 的支持情况存在差异。

造成的影响

由于各浏览器对除 INPUT 和 BUTTON 元素以外的其他元素的 "click" 方法的支持情况存在差异,将导致除 INPUT 和 BUTTON 元素以外的其他元素的 "click" 方法模拟的鼠标点击所触发的函数在某些浏览器中不能得到响应。

受影响的浏览器

所有浏览器

问题分析

在现行 HTML 4.01 规范中 “click” 方法仅可应用于 "type" 属性值为 "button" "checkbox" "radio" "reset" "submit" 的 INPUT 元素上。

但,HTML 5 草案中 HTMLElement 接口说明中存在 "click" 方法,这表示着在未来 HTML 发展趋势中,所有 HTML 元素均有可能拥有 "click" 方法。

详情可以参考 HTML 5 3.2.2 Elements in the DOM 中 HTMLElement 接口说明文档。

同时,在 IE 的厂商制定规范中也存在对 "click" 方法的描述,所有的 Element Constructor 均支持这个方法。

详情可以参考 MSND click Method 中相关描述。

由上可见,现行规范、规范草案、以及厂商标准均有差异。在新版本浏览器纷纷支持 HTML 5 草案规范的情况下,我们构建如下测试用例检测所有 HTML 元素对 "click" 方法的支持性。

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script>
    var tags = ['A','AREA','ABBR','ACRONYM','ADDRESS','B','BDO','BIG','BLOCKQUOTE','BR','BUTTON','CAPTION','CENTER','CITE','CODE',
                'COL','COLGROUP','DD','DEL','DIR','DIV','DFN','DL','DT','EM','FIELDSET','FONT','FORM','H1','H2','H3','H4','H5','H6',
                'HR','I','IMG','INPUT','INS','IFRAME','KBD','LABEL','LEGEND','LI','MAP','MENU','OBJECT','OL','EMBED','P','PRE','Q',
                'S','SAMP','SELECT','SMALL','SPAN','STRIKE','STRONG','SUB','SUP','TABLE','TBODY','TD','TEXTAREA','TFOOT','TH','THEAD',
                'TR','TT','U','UL','VAR'];
    var htmls = [
                '<a href ="javascript:void 0;">A</a>',
                '<img src="google.gif" usemap="#planetmap" /><map name="planetmap">          \
                 <area  shape="rect" coords="0,0,50,50" href ="javascript:void 0;"/></map>',
                '<abbr>ABBR</abbr>',
                '<acronym>ACRONYM</acronym>',
                '<address>ADDRESS</address>',
                '<b>B</b>',
                '<bdo>BDO</bdo>',
                '<big>BIG</big>',
                '<blockquote>BLOCKQUOTE</blockquote>',
                '<br/>',
                '<button type="button">BUTTON(button)</button>',
                '<button type="reset">BUTTON(reset)</button>',
                '<button type="submit">BUTTON(submit)</button>',
                '<table><caption>CAPTION</caption><tr><td></td></tr></table>',
                '<center>CENTER</center>',
                '<cite>CITE</cite>',
                '<code>CODE</code>',
                '<table><col/><tr><td>COL</td></tr></table>',
                '<table><colgroup ></colgroup><tr><td>COLGROUP</td></tr></table>',
                '<dd>DD</dd>',
                '<del>DEL</del>',
                '<dir>DIR</dir>',
                '<div>DIV</div>',
                '<dfn>DFN</dfn>',
                '<dl>DL</dl>',
                '<dt>DT</dt>',
                '<em>EM</em>',
                '<fieldset>FIELDSET</fieldset>',
                '<font>FONT</font>',
                '<form>FORM</form>',
                '<h1>H1</h1>',
                '<h2>H2</h2>',
                '<h3>H3</h3>',
                '<h4>H4</h4>',
                '<h5>H5</h5>',
                '<h6>H6</h6>',
                '<hr/>',
                '<i>I</i>',
                '<input type="text"/>',
                '<input type="checkbox"/>',
                '<input type="hidden"/>',
                '<input type="image"/>',
                '<input type="password"/>',
                '<input type="radio"/>',
                '<input type="reset"/>',
                '<input type="submit"/>',
                '<input type="file"/>',
                '<ins>INS</ins>',
                '<iframe  src="google.html"></iframe>',
                '<kbd>KBD</kbd>',
                '<label>LABEL</label>',
                '<fieldset><legend >LEGEND</legend>fieldset</fieldset>',
                '<li>LI</li>',
                '<menu>MENU</menu>',
                '<object  type="application/x-shockwave-flash"><param name="movie" value="google.gif" /></object>',
                '<ol>OL</ol>',
                '<embed  type="application/x-shockwave-flash" src="clock.swf" />',
                '<p>P</p>',
                '<pre>PRE</pre>',
                '<q>Q</q>',
                '<s>S</s>',
                '<samp>SAMP</samp>',
                '<select><option>SELECT</option></select>',
                '<small>SMALL</small>',
                '<span>SPAN</span>',
                '<strike>STRIKE</strike>',
                '<strong>STRONG</strong>',
                '<sub>SUB</sub>',
                '<sup>SUP</sup>',
                '<textarea >TEXTAREA</textarea>',
                '<table><tbody><tr><td>TABLE</td></tr></tbody></table>',
                '<table><tfoot><tr><td>TFOOT</td></tr></tfoot></table>',
                '<table><tbody><tr><th >TH</th></tr></tbody></table>',
                '<table><thead ><tr><td>THEAD</td></tr></thead></table>',
                '<table><tbody><tr><td>TR</td></tr></tbody></table>',
                '<tt>TT</tt>',
                '<u>U</u>',
                '<ul>UL</ul>',
                '<var>VAR</var>'
        ];
    windowfunction element_click(){
        document.getElementById("container").style.display="block";
        document.getElementById("info1").style.display="block";
        document.getElementById("info2").style.display="block";
        for(var i in htmls){
            document.getElementById("container").innerHTML+=htmls[i];
            document.getElementById("container").innerHTML+="<br/>";
            document.getElementById("inited").onclick="";
        }
        var flag;
        for(var i in tags){
      flag=0;
            if(document.getElementsByTagName(tags[i])){
                var elements=document.getElementsByTagName(tags[i]);
                if(tags[i]=="BUTTON"||tags[i]=="INPUT"){
                 for(var j=0;j<elements.length;j++){
                     flag=0;
                     try{
                            elements[j].click();
                        }catch(e){
                           document.getElementById("info1").innerHTML+=i+"."+tags[i]+"[type="+elements[j].type+"] :"+e+"<br/>";
                           flag=1;
                        }
                     if(flag==0)
                        document.getElementById("info2").innerHTML+=i+"."+tags[i]+"[type="+elements[j].type+"] :"+"支持Click()<br/>";
                    }
                }
                else{
                    try{
                        elements[0].click();
                    }
                    catch(e){
                        document.getElementById("info1").innerHTML+=i+"."+tags[i]+" :"+e+"<br/>";
                        flag=1;
                        }
                    if(flag==0)
                        document.getElementById("info2").innerHTML+=i+"."+tags[i]+" :"+"支持Click()<br/>";
                    }
                }
            }
  }
</script>
<input  type="button" value="点击此按键开始测试所有 HTML 标签的 Click 方法支持程度" id="inited" onclick="element_click()"/>
<div id="container" style="border:1px solid black;display:none;"></div>
<div id="info1" style="border:1px solid red;display:none;"></div>
<div id="info2" style="border:1px solid blue;display:none;"></div>
</body>
</html>

以上代码中数组 "htmls" 为向页面输出需要测试的所有 HTML 元素,数组 "tags" 用于之后获得这些 HTML 元素时 "getElementsByTagName" 的函数参数,"element_click" 方法的主要思想是首先将数组 "htmls" 中的元素以 HTML 元素的形式输出到页面,然后通过 "getElementsByTagName" 方法并将数组 "tags" 中的元素做为其形参获得每一个上一步骤中输出到页面中的元素,最后通过 try{...}catch(Exception e){...} 检测每一个 HTML 元素在执行 "click" 方法时是否发生异常,如发生异常则捕获并将其输出,否则表示该元素支持 "click" 方法。

测试结果归纳如下:

  IE6 IE7 IE8 Opera Firefox Safari Chrome
INPUT[type=text]
INPUT[type=password]
INPUT[type=radio]
INPUT[type=checkbox]
INPUT[type=button]
INPUT[type=submit]
INPUT[type=image]
INPUT[type=hidden]
INPUT[type=reset]
INPUT[type=submit]
INPUT[type=file]1
BUTTON[type=button]
支持 支持
其他 HTML 元素 支持 不支持

从上例运行结果的归纳总结可见:

  • IE6 IE7 IE8 Opera 中,所有 HTML 元素均支持直接使用 "click" 方法触发单击事件。
  • Firefox Safari Chrome 中,仅支持对 INPUT BUTTON 元素,直接使用 "click" 方法触发其单击事件。

【注】:IE6 IE7 IE8 Safari Chrome 中,调用 input[type=file] 元素的 "click" 方法会使浏览器弹出选择文件对话框,而 Firefox 和 Opera 则没有将选择文件对话框打开,这可能是出于某种安全因素考虑。

综上所述,BUTTON 元素的 "click" 方法已经被所有浏览器支持,超出了现行 HTML 4.01 规范,正在贴近 HTML 5 草案。另外,Opera 更好的支持了 HTML 5 草案,而 IE6 IE7 IE8 完全遵循了自身的厂商扩展定义。

解决方案

建议尽量避免对除 INPUT 和 BUTTON 元素以外的其他元素通过 "click" 方法模拟鼠标点击事件。

如需对其元素使用 "click" 方法触发 "onClick" 事件处理程序,可以通过以下两种方式解决:

  • 由于大多数情况下调用 "click" 方法所实现的无非是执行某一元素所绑定的事件处理函数,因此可以直接调用该元素所对应的 "click" 事件处理函数。
  • 或者使用 DOM-Level-2-Events 标准内 DocumentEvent interfaceEvent interfaceEvent registration interfaces 相关定义中的 "createEvent" " initEvent" 以及 "dispatchEvent"方法建立 "click" 事件并派发出去。如:
    function createEvent (eventTarget,eventName){
        try{
            if(eventTarget.dispatchEvent){
                var evt = document.createEvent("MouseEvents");
                evt.initEvent(eventName,false,true);
                eventTarget.dispatchEvent(evt);
            }else if(eventTarget.fireEvent){
                eventTarget.fireEvent('on'+eventName);
            }else{
                eventTarget[ type ]();
            }
        }catch(e){
            alert(e);
        }
    }
    createEvent(HTMLElement,'click');
    

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6.11
8.0.552.11 dev
Safari 5.0.2
Opera 10.63
测试页面: click.html
本文更新时间: 2010-10-18

关键字

click onclick