苦逼的程序员经常遇到种种奇怪的需求,经常要想些奇怪的方法来解决问题。
场景:
最近用一个插件来展示大量图片,该插件封装逻辑很复杂,文档几乎为零。要修改其代码几乎是不可能完成的任务。因此我想要手工触发一个鼠标点击事件,以此激活其内部处理代码,完成相应的操作,不修改插件的任何代码、不用阅读任何插件的代码。
简单地触发鼠标事件很容易,如果用jQuery就更容易了: $("#container").trigger("click");
但我需要模拟鼠标在容器的某个位置点击。仔细阅读javascript的文档,找到了激活特定位置鼠标点击事件的方法。经测试,我用的插件收到mouseDown、mouseUp两个事件、且位置没有发生变化时,就会执行我需要的操作。那么我的代码如下:
function simulateClick(){ //点击位置为屏幕中间 var sx= window.innerWidth/2,sy= window.innerHeight/2,cx= sx,cy=sy; var eventDown = document.createEvent("MouseEvents"); eventDown.initMouseEvent("mousedown",true,true,window,0, sx,sy,cx,cy,false,false,false,false,0,null); var eventUp = document.createEvent("MouseEvents"); eventUp.initMouseEvent("mouseup",true,true,window,0, sx,sy,cx,cy,false,false,false,false,0,null); $("#container")[0].dispatchEvent(eventDown); $("#container")[0].dispatchEvent(eventUp); }
后来又用这样方法解决了插件不支持触屏移动的问题。通过附加事件、跟踪输出,发现插件不能很好地响应touchstart、touchmove、touchend事件,其中touchmove事件直接无视,如果触屏后立即移动,那么不会触发mousedown、mousemove、mouseup事件,总之一句话,需要将touchstart/touchmove/touchend转化为mousedown/mousemove/mouseup事件。
以上这种需要可以用自定义事件、然后触发的机制来解决。
/** * event为jquery的事件。真正的事件为event.originalEvent * 使用新的方法处理。http://wallimn.itey.com */ function touchEventToMouseEvent(event,eventType){ if(!event.originalEvent || !event.originalEvent.targetTouches || event.originalEvent.targetTouches.length!=1) return null; var te = event.originalEvent.targetTouches[0]; var clientX = te.clientX,clientY=te.clientY,screenX=te.screenX,screenY=te.screenY; var simEvent = new MouseEvent(eventType,{clientX:clientX,clientY:clientY,screenX:screenX,screenY:screenY,button:0,buttons:0}); return simEvent; } function findElm(){ var elm = $(".pivot_layer[title]"); elm.bind("touchmove",function(e){ var simEvent = touchEventToMouseEvent(e,"mousemove"); if(simEvent!=null){ $(this)[0].dispatchEvent(simEvent); } }); elm.bind("touchstart",function(e){ console.log("touchstart"); var simEvent = touchEventToMouseEvent(e,"mousedown"); if(simEvent!=null){ $(this)[0].dispatchEvent(simEvent); } }); elm.bind("touchend",function(e){ console.log("touchend"); var simEvent = touchEventToMouseEvent(e,"mouseup"); if(simEvent!=null){ $(this)[0].dispatchEvent(simEvent); } }); } } $(function(){ findElm(); });
注:initMouseEvent是个将要废弃的方法,推荐使用new MouseEvent()方法来代替。上述代码基于jQuery插件。