打印

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