Categories: Js/AJAX | Tags: , , | Views: 1,190

 

之所以同时加上引号,是因为真正的同时,除了机器人,是不可能做到的。

这个是利用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);

 

这篇文章来自 迷途知返(PWWANG.COM), 转载请注明出处。 版权说明

  1. October 29th, 2009 at 21:17
    Reply | Quote | #1

    太高深,好好学习下!

;) :| :x :twisted: :roll: :oops: :o :mrgreen: :lol: :idea: :evil: :cry: :arrow: :P :D :?: :? :) :( :!: 8O 8)

你可以使用@somebody:开头, 来邮件通知somebody你回复了他的留言(用户名区分大小写).