|
Oct
29
|
|
之所以同时加上引号,是因为真正的同时,除了机器人,是不可能做到的。
这个是利用jQuery的事件管理机制来实现的,并把它写成了一个jQuery插件。
在Firefox中表现完美, 在IE中能够实现想要的功能,但是总是有些不尽如人意。
在IE中左键的button值是1,右键是0;而在Firefox中左键是0,右键是2.
问题倒不在这里,问题在于,如果你在IE中先点右键,再很短的时间内再点左键,你会发现得到的button值是3!并且如果是这么简单也就好了,直接检测button值,如果是3,就直接执行事件就行了。可是问题总不是想象中的那样简单,在button=3的事件执行完之后,IE还会激发一个button=1的事件(先点的右键,那点的左键)。这在处理起来就麻烦多了。
我的思路和网上想实现这类功能的人的思路大致相同,也是通过一个计时器来判断。
具体思路是这样的:
这个插件可以处理鼠标左右键的同时点击(click),鼠标按下(mousedown),鼠标弹起(mouseup)事件。在讲思路的时候就以点击为
例。
首先我们必须先找出所有绑定为点击的事件,unbind它们,因为要阻止它们在一点击鼠标的时候就执行。
在找这些事件的时候还是颇费了一番功夫的。因为jQuery的源码还没有真正的读通。所以机制也并没有弄很清楚明白。jQuery将事件存在了一个缓存里面(jQuery.cache),但是如果从这个缓存里把这些事件取出来?关键问题是找到元素对应的在缓存的位置,我找遍了jQuery(…)就是没有这样的公有方法。于是用了一个小trick,我们知道jQuery允许我们给一个元素绑定data,而这个data也是存在缓存里的。所以我就可以赋一个唯一的属性值给data(时间戳或者随机数),再后再通过这个唯一值找到这个元素并找到存储的事件。
这时候我们就可以处理左右键的事件了。因为无论左键还是右键先点,我们要达到的效果是一样的,所以这里只说一下其中一个键点击的事件。
当点击一个键的时候,我们先需要先判断另一个键是否已经点击,如果还没有点击,这时候判断一下时间差(这个是专为IE设计的。。。因为IE会引起一个button=1的事件,在button=3的事件执行之后,就把时间变量设置为当前时间),如果不在时间差内,就等待另一个按键的点击。如果另一个键已经点击了的话,那就直接判断时间差,在时间差内就执行给定的事件;如果不在,就执行原有的事件。
这样,在bindLR后,也不影响原来已经bind的事件的执行(会有设定时间的延时,为了等待另一个键的点击),在unbindLR之后,也能够恢复原来已经bind的事件,我没有采用循环绑定,所以在绑定了bindLR事件之后,无法再用unbind来原有事件的绑定,并且,unbindLR现在的功能有限,只能解除所有的bindLR事件,并不能解除指定事件的绑定。
jquery.LRmouse.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | /** * * jquery.LRmouse 1.0.0 * * Author: pwwang ( http://pwwang.com ) * 2009.10.26 * * Bind an event handle to a listener that * LButton and RButton of the mouse act * ( click, mousedown, mouseup ) "simultaneously" * * It works on both IE and Firefox, distinguishedly, * however, it performs perfectly in Firefox; not * exactly ideally in IE. * **/ (function($){ $.bindLR = function( elem, type, data, fn, intv ){ var L_BUTTON = $.browser.msie ? 1 : 0 ; var R_BUTTON = $.browser.msie ? 0 : 2 ; var LR_BUTTON = 3; // ie var orgType = type.substr(2); var L_flag = false; var R_flag = false; var getTime = function(){ return +new Date; }; var lrId = getTime(); // for finding the elem in $.cache // a trick, 'cz I don't know how to // find the function directly elem.data('lrId', lrId); var orgFns = []; for( var i in $.cache ){ // find original binded functions if( $.cache[i]['lrId'] == lrId ){ var fns = $.cache[i]['events'][orgType]; for( var j in fns ){ orgFns.push( fns[j] ); elem.unbind( orgType, fns[j] ); } //remove it elem.removeData('lrId'); break; } } elem.data('lrTempEvents',orgFns); var timer = getTime(); var timeOut; var reset = function(){ L_flag = false; R_flag = false; clearTimeout( timeOut ); }; var orgFnHandle = function(e, data){ reset(); for( var i=0; i<orgFns.length; i++ ){ orgFns[i].call(elem, e, data); } }; var L_event = function(e, data){ if( !R_flag ){ //waiting // if LR_BUTTON, do NOT wait // LR_BUTTON in ie will call L_BUTTON event if( getTime() - timer > intv ){ L_flag = true; timer = getTime(); timeOut = setTimeout( function(){orgFnHandle(e, data);}, intv+1 ); } } else { reset(); var deltT = getTime() - timer; if( deltT <= intv ){ fn.call(elem, e, data); } else { orgFnHandle(e, data); } } }; var R_event = function(e, data){ if( !L_flag ){ if( getTime() - timer > intv ){ R_flag = true; timer = getTime(); timeOut = setTimeout( function(){orgFnHandle(e, data);}, intv+1 ); } } else{ reset(); var deltT = getTime()-timer; if( deltT <= intv ){ fn.call(elem, e, data) } else { orgFnHandle(e, data); } } } var eventHandle = function(e, data){ if( L_BUTTON === e.button ) L_event (e, data); else if( R_BUTTON === e.button ) R_event (e, data); else if( LR_BUTTON === e.button ) { //ie timer = getTime(); fn.call(elem, e, data); } }; //ban context menu; elem.bind('contextmenu', function(){ return false; }); //bind new elem.bind( orgType, data, eventHandle ); }; $.unbindLR = function(elem, type){ elem.unbind('contextmenu'); elem.unbind( type ); var orgType = type.substr(2); elem.unbind( orgType ); var lrId = Math.random(); elem.data('lrId', lrId); for( var i in $.cache ){ if( $.cache[i]['lrId'] == lrId ){ var fns = $.cache[i]['lrTempEvents']; for( var j in fns ){ elem.bind( orgType, function(){ fns[j].apply(elem,arguments) }); } //remove it elem.removeData('lrId'); elem.removeData('lrTempEvents'); break; } } }; $.fn.bindLR = function(type, data, fn, intv){ if( $.isFunction( data ) ){ intv = fn || 500; fn = data; data = {}; } else { data = data || {}; fn = fn || {}; intv = intv || 500; } // lr bind for $(...).trigger() this.bind(type,data,fn); if( type.substr(0,2)=='lr' ){ $.bindLR( this, type, data, fn, intv ); } return this; }; $.fn.unbindLR = function(type){ $.unbindLR( this,type ); return this; } })(jQuery); |


太高深,好好学习下!