感言:
苦逼的程序员经常遇到种种奇怪的需求, 经常要想些奇怪的方法来解决问题.
场景:
最近用一个插件来展示大量图片, 该插件封装逻辑很复杂, 文档几乎为零. 要修改其代码几乎是不可能完成的任务. 因此我想要手工触发一个鼠标点击事件, 以此激活其内部处理代码, 完成相应的操作, 不修改插件的任何代码, 不用阅读任何插件的代码.
简单地触发鼠标事件很容易, 如果用 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 插件.
来源: http://wallimn.iteye.com/blog/2358847