职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 508|回复: 9

js模拟点击那点事

[复制链接]
broken 发表于 2011-8-19 09:28 | 显示全部楼层 |阅读模式
在实际的应用开发中,我们会常常用到JS的模事件,但有时会遇到一些问题,比如说点击事件,举个简单的例子,点击表单外的“提交”按钮来提交表单。上代码吧。
Html:
Html代码  
<h3>请单击“提交”,测试提交按钮的单击事件也被触发了。</h3>  
<button id="btn">提交</button>  
<form action="#" method="get" id="form">  
  <input type="text" name="site" value="www.woiweb.net" readonly/>  
  <input id="subbtn" type="submit" value="先别点击此按钮提交" onclick="alert('我已经提交了');"/>  
</form>  

<h3>请单击“提交”,测试提交按钮的单击事件也被触发了。</h3>
<button id="btn">提交</button>
<form action="#" method="get" id="form">
  <input type="text" name="site" value="www.woiweb.net" readonly/>
  <input id="subbtn" type="submit" value="先别点击此按钮提交" onclick="alert('我已经提交了');"/>
</form>
Javscript:
Js代码  
<script type="text/javascript">   
  var sub = document.getElementById("subbtn");   
  var btn = document.getElementById("btn");   
//通用方法   
btn.onclick = function() {   
sub.click();   
}   
</script>  

<script type="text/javascript">
  var sub = document.getElementById("subbtn");
  var btn = document.getElementById("btn");
//通用方法
btn.onclick = function() {
sub.click();
}
</script>
经过测试,IE,FF,Chrome,Opera,Safari都没有问题,均可正常提交表单。
但在实际的设计中,为了让提交按钮更好看,buildder经常把它们用a标签来处理,加个背景图片来模拟按钮,我们仍然用上面的思路来尝试,增加一个a标签,让它来提交表单,我们仅修改html。
Html:
Html代码  
<h3>请单击“提交”,测试提交按钮的单击事件也被触发了。</h3>  
<button id="btn">提交</button>  
<form action="#" method="get" id="form">  
  <input type="text" name="site" value="www.woiweb.net" readonly/>  
  <!--<input id="subbtn" type="submit" value="先别点击此按钮提交" onclick="alert('我已经提交了');"/> -->  
  <a id="subbtn" href="javascript:;" onclick="alert('在此调用提交表单的方法')">模拟提交按钮</a>  
</form>  

<h3>请单击“提交”,测试提交按钮的单击事件也被触发了。</h3>
<button id="btn">提交</button>
<form action="#" method="get" id="form">
  <input type="text" name="site" value="www.woiweb.net" readonly/>
  <!--<input id="subbtn" type="submit" value="先别点击此按钮提交" onclick="alert('我已经提交了');"/> -->
  <a id="subbtn" href="javascript:;" onclick="alert('在此调用提交表单的方法')">模拟提交按钮</a>
</form>
Javascript:
Js代码  
<script type="text/javascript">   
  var sub = document.getElementById("subbtn");   
  var btn = document.getElementById("btn");   
//通用方法   
btn.onclick = function() {   
sub.click();   
}   
</script>  

<script type="text/javascript">
  var sub = document.getElementById("subbtn");
  var btn = document.getElementById("btn");
//通用方法
btn.onclick = function() {
sub.click();
}
</script>
运行后,问题出现了,IE、FF、Opera均OK,但Chrome和Safari不能正常运行,后来网上搜索了下,发现a标签并不是和按钮一样有onclick()事件的,解决办法是针对 IE 和 FF编写不同的逻辑,JS代码如下:
javascript:
Js代码  
<script type="text/javascript">   
  var sub = document.getElementById("subbtn");   
  var btn = document.getElementById("btn");   
//通用方法   
btn.onclick = function() {   
   //sub.click();   
   if (/msie/i.test(navigator.userAgent)) //IE   
   {   
      sub.fireEvent("onclick");   
   } else {   
      var e = document.createEvent('MouseEvent');   
      e.initEvent('click', false, false);   
      sub.dispatchEvent(e);   
   }   
}   
</script>  

<script type="text/javascript">
  var sub = document.getElementById("subbtn");
  var btn = document.getElementById("btn");
//通用方法
btn.onclick = function() {
   //sub.click();
   if (/msie/i.test(navigator.userAgent)) //IE
   {
      sub.fireEvent("onclick");
   } else {
      var e = document.createEvent('MouseEvent');
      e.initEvent('click', false, false);
      sub.dispatchEvent(e);
   }
}
</script>
至此,问题解决,虽然这个问题很简单,但很容易被大家忽略,贴出来和大家一起分享。

语法:
createEvent(eventType)
参数描述
eventType想获取的 Event 对象的事件模块名。关于有效的事件类型列表,请参阅”说明”部分。

返回值
返回新创建的 Event 对象,具有指定的类型。
抛出
如果实现支持需要的事件类型,该方法将抛出代码为 NOT_SUPPORTED_ERR 的 DOMException 异常。
说明
该方法将创建一种新的事件类型,该类型由参数 eventType 指定。注意,该参数的值不是要创建的事件接口的名称,而是定义那个接口的 DOM 模块的名称。
下表列出了 eventType 的合法值和每个值创建的事件接口:
参数事件接口初始化方法
HTMLEventsHTMLEventiniEvent()
MouseEventsMouseEventiniMouseEvent()
UIEventsUIEventiniUIEvent()

用该方法创建了 Event 对象以后,必须用上表中所示的初始化方法初始化对象。关于初始化方法的详细信息,请参阅 Event 对象参考。
该方法实际上不是由 Document 接口定义的,而是由 DocumentEvent 接口定义的。如果一个实现支持 Event 模块,那么 Document 对象就会实现 DocumentEvent 接口并支持该方法。

参考资料:http://www.w3school.com.cn/xmldom/met_document_createevent.asp
本文链接:http://www.woiweb.net/js-simulate-click-event.html

话说我当年 发表于 2011-8-19 09:28 | 显示全部楼层
我向来都是对form进行submit的,不过倒没有注意过兼容性的问题。

江南枫 发表于 2011-8-19 09:28 | 显示全部楼层
我也来一个,Ext下扩展Ext.Element,使它支持fireEvent模拟事件。(用于开发测试代码)
开发的时候参考了w3c dom相关文档,实测鼠标点击事件是一切OK的

Js代码  
(function(){   
    var eventTypes = ["HTMLEvents", "MouseEvents", "UIEvents", "MutationEvents", "Events"];   
    var eventMap = {   
        HTMLEvents : {   
            abort : true,   
            blur : true,   
            change : true,   
            error : true,   
            focus : true,   
            load : true,   
            reset : true,   
            resize : true,   
            scroll : true,   
            select : true,   
            submit : true,   
            unload : true  
        },   
        UIEvents : { // 包含MouseEvents   
            DOMActivate : true,   
            DOMFocusIn : true,   
            DOMFocusOut : true,   
            keydown : true,   
            keypress : true,   
            keyup : true  
        },   
        MouseEvents : {   
            click : true,   
            mousedown : true,   
            mousemove : true,   
            mouseout : true,   
            mouseover : true,   
            mouseup : true  
        },   
        MutationEvents : {   
            DOMAttrModified : true,   
            DOMNodeInserted : true,   
            DOMNodeRemoved : true,   
            DOMCharacterDataModified : true,   
            DOMNodeInsertedIntoDocument : true,   
            DOMNodeRemovedFromDocument : true,   
            DOMSubtreeModified : true  
        },   
        Events : {   
            // 所有事件   
        }   
    };   
      
    var getType = function(ename){   
        var foundType = "Events";   
        Ext.each(eventTypes, function(type){   
            var map = eventMap[type];   
            if(map.hasOwnProperty(ename) && map[ename] === true){   
                foundType = type;   
                return false;   
            }   
        });   
        return foundType;   
    };   
      
    var defaultCfg = {   
        canBubble : true,   
        cancelable : true,   
        view : window,   
        detail : 0,   
        screenX : 0,   
        screenY : 0,   
        clientX : 0,   
        clientY : 0,   
        ctrlKey : false,   
        altKey : false,   
        shiftKey : false,   
        metaKey : false,   
        button : 0,   
        prevValue : null,   
        newValue : null,   
        attrName : null,   
        attrChange : 1   
    };   
    var getDefalutCfg = function(dom, cfg){   
        cfg = cfg || {};   
        Ext.applyIf(cfg, defaultCfg);   
           
        cfg.relatedTarget = cfg.relatedTarget || dom;   
        return cfg;   
    };   
    Ext.override(Ext.Element, {   
        /*  
         * 模拟html dom事件  
         */  
        fireEvent : function(ename, cfg){   
            var e, type, dom = this.dom;   
            ename = ename || "";   
            if(Ext.isIE){   
                e = document.createEventObject();   
                Ext.apply(e, cfg);   
                dom.fireEvent("on" + ename, e);   
            }else{   
                type = getType(ename);   
                cfg = getDefalutCfg(dom, cfg);   
                e = document.createEvent(type);   
                switch(type){   
                    case "UIEvents":   
                        e.initUIEvent(ename, cfg.canBubble, cfg.cancelable, cfg.view, cfg.detail);   
                        break;   
                    case "MouseEvents":   
                        e.initMouseEvent(ename, cfg.canBubble, cfg.cancelable, cfg.view, cfg.detail,   
                                    cfg.screenX, cfg.screenY, cfg.clientX, cfg.clientY,   
                                    cfg.ctrlKey, cfg.altKey, cfg.shiftKey, cfg.metaKey,   
                                    cfg.button, cfg.relatedTarget);   
                        break;   
                    case "MutationEvent":   
                        e.initMutationEvent(ename, cfg.canBubble, cfg.cancelable, cfg.relatedNode,   
                                    cfg.prevValue, cfg.newValue, cfg.attrName, cfg.attrChange);   
                        break;   
                    default: // Events   
                        e.initEvent(ename, cfg.canBubble, cfg.cancelable);   
                        break;   
                }   
                dom.dispatchEvent(e);   
            }   
        }   
    });   
  
})();  

(function(){
        var eventTypes = ["HTMLEvents", "MouseEvents", "UIEvents", "MutationEvents", "Events"];
        var eventMap = {
                HTMLEvents : {
                        abort : true,
                        blur : true,
                        change : true,
                        error : true,
                        focus : true,
                        load : true,
                        reset : true,
                        resize : true,
                        scroll : true,
                        select : true,
                        submit : true,
                        unload : true
                },
                UIEvents : { // 包含MouseEvents
                        DOMActivate : true,
                        DOMFocusIn : true,
                        DOMFocusOut : true,
                        keydown : true,
                        keypress : true,
                        keyup : true
                },
                MouseEvents : {
                        click : true,
                        mousedown : true,
                        mousemove : true,
                        mouseout : true,
                        mouseover : true,
                        mouseup : true
                },
                MutationEvents : {
                        DOMAttrModified : true,
                        DOMNodeInserted : true,
                        DOMNodeRemoved : true,
                        DOMCharacterDataModified : true,
                        DOMNodeInsertedIntoDocument : true,
                        DOMNodeRemovedFromDocument : true,
                        DOMSubtreeModified : true
                },
                Events : {
                        // 所有事件
                }
        };
       
        var getType = function(ename){
                var foundType = "Events";
                Ext.each(eventTypes, function(type){
                        var map = eventMap[type];
                        if(map.hasOwnProperty(ename) && map[ename] === true){
                                foundType = type;
                                return false;
                        }
                });
                return foundType;
        };
       
        var defaultCfg = {
                canBubble : true,
                cancelable : true,
                view : window,
                detail : 0,
                screenX : 0,
                screenY : 0,
                clientX : 0,
                clientY : 0,
                ctrlKey : false,
                altKey : false,
                shiftKey : false,
                metaKey : false,
                button : 0,
                prevValue : null,
                newValue : null,
                attrName : null,
                attrChange : 1
        };
        var getDefalutCfg = function(dom, cfg){
                cfg = cfg || {};
                Ext.applyIf(cfg, defaultCfg);
               
                cfg.relatedTarget = cfg.relatedTarget || dom;
                return cfg;
        };
        Ext.override(Ext.Element, {
                /*
                 * 模拟html dom事件
                 */
                fireEvent : function(ename, cfg){
                        var e, type, dom = this.dom;
                        ename = ename || "";
                        if(Ext.isIE){
                                e = document.createEventObject();
                                Ext.apply(e, cfg);
                                dom.fireEvent("on" + ename, e);
                        }else{
                                type = getType(ename);
                                cfg = getDefalutCfg(dom, cfg);
                                e = document.createEvent(type);
                                switch(type){
                                        case "UIEvents":
                                                e.initUIEvent(ename, cfg.canBubble, cfg.cancelable, cfg.view, cfg.detail);
                                                break;
                                        case "MouseEvents":
                                                e.initMouseEvent(ename, cfg.canBubble, cfg.cancelable, cfg.view, cfg.detail,
                                                                        cfg.screenX, cfg.screenY, cfg.clientX, cfg.clientY,
                                                                        cfg.ctrlKey, cfg.altKey, cfg.shiftKey, cfg.metaKey,
                                                                        cfg.button, cfg.relatedTarget);
                                                break;
                                        case "MutationEvent":
                                                e.initMutationEvent(ename, cfg.canBubble, cfg.cancelable, cfg.relatedNode,
                                                                        cfg.prevValue, cfg.newValue, cfg.attrName, cfg.attrChange);
                                                break;
                                        default: // Events
                                                e.initEvent(ename, cfg.canBubble, cfg.cancelable);
                                                break;
                                }
                                dom.dispatchEvent(e);
                        }
                }
        });

})();


使用方法:
Js代码  
// 模拟左键点击按钮(mousedown和mouseup并不是必须,只是为了更真实模拟)   
el.fireEvent("mousedown", {button:0});   
el.fireEvent("mouseup", {button:0});   
el.fireEvent("click", {button:0});  

// 模拟左键点击按钮(mousedown和mouseup并不是必须,只是为了更真实模拟)
el.fireEvent("mousedown", {button:0});
el.fireEvent("mouseup", {button:0});
el.fireEvent("click", {button:0});


shmilyyu 发表于 2011-8-19 09:28 | 显示全部楼层
为什么搞这么复杂,直接在div上加onclick事件,再调用form的submit()不行吗

醉倚西风 发表于 2011-8-19 09:29 | 显示全部楼层
hh161151 写道
为什么搞这么复杂,直接在div上加onclick事件,再调用form的submit()不行吗

人家要触发原始提交链接上的动作,其实我感觉用form的onSubmit比较好。。。

但有些时候确实需要模拟事件,比如写自动测试代码

天上智喜 发表于 2011-8-19 09:29 | 显示全部楼层
学习啦。其实javascript这块,我觉得就是操作属性,这些简单觉得没必要大做文章

 楼主| broken 发表于 2011-8-19 09:29 | 显示全部楼层
jack1210 写道
学习啦。其实javascript这块,我觉得就是操作属性,这些简单觉得没必要大做文章

等某天你需要的时候就觉得很有必要了

找不到我 发表于 2011-8-19 09:29 | 显示全部楼层
关键还是鼠标的动作

AddEventListener  和 AttachEvent没用啊

咕~~(╯﹏╰)b

天上智喜 发表于 2011-8-19 09:29 | 显示全部楼层
去研究一下jq的trigger怎么实现,应该有所收获

走失的猫咪 发表于 2011-8-19 09:29 | 显示全部楼层
勘误下:FF中A是没有click方法的。仅IE和Opera有。
您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-4-25 17:09 , Processed in 0.131106 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表