nexus site path corrected
[portal.git] / ecomp-portal-FE / client / bower_components / jquery.event.drag-new / event.linger / jquery.event.linger.js
1 /*! 
2  * jquery.event.linger - v 1.0.0 
3  * Copyright (c) 2010 Three Dub Media - http://threedubmedia.com
4  * Open Source MIT License - http://threedubmedia.com/code/license
5  */
6 // Created: 2008-06-02
7 // Updated: 2010-09-13
8 // REQUIRES: jquery 1.4.2+
9
10 ;(function($){ // secure $ jQuery alias
11
12 // add the jquery instance method
13 $.fn.linger = function( str, arg, opts ){
14         // figure out the event type
15         var type = typeof str == "string" ? str : "",
16         // figure out the event handler...
17         fn = $.isFunction( str ) ? str : $.isFunction( arg ) ? arg : null;
18         // fix the event type
19         if ( type.indexOf("linger") !== 0 ) 
20                 type = "linger"+ type;
21         // were options passed
22         opts = ( str == fn ? arg : opts ) || {};
23         // trigger or bind event handler
24         return fn ? this.bind( type, opts, fn ) : this.trigger( type );
25 };
26
27
28 // local refs (increase compression)
29 var $event = $.event, 
30 $special = $event.special,
31 // special event configuration
32 linger = $special.linger = {
33         
34         // default settings
35         defaults: {
36                 speed: 100, // speed limit (pixels per second)
37                 delay: 100, // milliseconds per speed check
38                 persist: 400 // milliseconds after mouseleave
39         },
40         
41         // the key name for stored data
42         datakey: "lingerdata",
43         
44         // count bound related events
45         add: function( obj ){
46                 // read the interaction data
47                 var data = $.data( this, linger.datakey ),
48                 // read any passed options 
49                 opts = obj.data || {};
50                 // count another realted event
51                 data.related += 1;
52                 // extend data options bound with this event
53                 // don't iterate "opts" in case it is a node 
54                 $.each( linger.defaults, function( key, def ){
55                         if ( opts[ key ] !== undefined )
56                                 data[ key ] = opts[ key ];
57                 });
58         },
59         
60         // forget unbound related events
61         remove: function(){
62                 $.data( this, linger.datakey ).related -= 1;
63         },
64         
65         // configure interaction
66         setup: function(){
67                 // check for related events
68                 if ( $.data( this, linger.datakey ) ) 
69                         return;
70                 // initialize the drag data with copied defaults
71                 var data = $.extend({ related:0 }, linger.defaults );
72                 // store the interaction data
73                 $.data( this, linger.datakey, data );
74                 // bind the mouse events with data
75                 $event.add( this, "mouseenter mouseleave", linger.handler, data );
76         },
77         
78         // destroy configured interaction
79         teardown: function(){
80                 // check for related events
81                 if ( $.data( this, linger.datakey ).related ) 
82                         return;
83                 // remove the stored data
84                 $.removeData( this, linger.datakey );
85                 // remove the mouse events
86                 $event.remove( this, "mouseenter mousemove mouseleave", linger.handler );
87         },
88         
89         // handle mouse events
90         handler: function( event ){ 
91                 var data = event.data || {};
92                 // initialize props for new interaction
93                 if ( event.type == "mouseenter" && !data.lingered ){
94                         // mouse distance squared
95                         data.dist2 = 0; 
96                         // ( speed * time ) squared
97                         data.limit = Math.pow( data.speed * ( data.delay/1e3 ), 2 );
98                         // the interacted element
99                         data.elem = this; 
100                         // handle the start event (handler may return false to cancel)
101                         if ( linger.hijack( event, "lingerstart", this ) ){ 
102                                 // store the event, to compare later
103                                 data.event = event; 
104                                 // begin tracking the mouse movement
105                                 $event.add( this, "mousemove", linger.handler, data ); 
106                                 // start comparing mouse speed at fixed intervals
107                                 data.timer = setTimeout(function(){ 
108                                         // check the current speed against the limit
109                                         if ( data.dist2 <= data.limit )
110                                                 // handle the linger event (handler may return false to cancel)
111                                                 data.lingered = linger.hijack( data.event, "linger", data.elem );
112                                         // stop tracking the mouse
113                                         if ( data.lingered )  
114                                                 $event.remove( data.elem, "mousemove", linger.handler );                
115                                         // recurse
116                                         else
117                                                 data.timer = setTimeout( arguments.callee, data.delay );
118                                         // reset distance for next comparison
119                                         data.dist2 = 0;
120                                 }, data.delay ); 
121                         }
122                 }
123                 // stop if not properly initialized
124                 if ( !data.event )
125                         return;
126                 // handle other events  
127                 switch ( event.type ){
128                         // mouse re-entry
129                         case data.lingered && 'mouseenter':
130                                 // stop the current timer
131                                 clearTimeout( data.timer ); 
132                                 break;
133                         // track mouse movement
134                         case 'mousemove': 
135                                 // distance² = x² + y²
136                                 data.dist2 += Math.pow( event.pageX - data.event.pageX, 2 ) 
137                                         + Math.pow( event.pageY - data.event.pageY, 2 ); 
138                                 // store current event  
139                                 data.event = event; 
140                                 break;
141                         // handle leaving after lingering
142                         case data.lingered && 'mouseleave': 
143                                 // optionally delay the end event 
144                                 data.timer = setTimeout(function(){
145                                         // handle the end event, flip flag for lingering
146                                         data.lingered = !linger.hijack( event, "lingerend", data.elem );
147                                         // if still lingering, recurse
148                                         if ( data.lingered )
149                                                 setTimeout( arguments.callee, data.persist );
150                                 }, data.persist );
151                                 break;
152                         // handle leaving after no lingering
153                         case !data.lingered && 'mouseleave':            
154                                 // stop the current timer
155                                 clearTimeout( data.timer ); 
156                                 // stop tracking the mouse movement
157                                 $event.remove( data.elem, "mousemove", linger.handler ); 
158                                 // clean the data for next interaction
159                                 data.event = null;
160                                 break;
161                 } 
162         },
163                 
164         // re-use event object for custom events
165         hijack: function( event, type, elem ){ 
166                 // remember the original event and type
167                 var result, orig = { 
168                         event: event.originalEvent, 
169                         type: event.type 
170                 };
171                 // modify the event type
172                 event.type = type;
173                 // remove the original event
174                 event.originalEvent = null;
175                 // remove any previous event result
176                 event.result = null;
177                 // handle the custom event
178                 result = $event.handle.call( elem, event );
179                 // restore the original event & type
180                 event.type = orig.type;
181                 event.originalEvent = orig.event;
182                 // return handled result
183                 return ( result !== false );
184         }
185 };
186
187 // share the same special event configuration with related events...
188 $special.lingerstart = $special.lingerend = linger;
189         
190 })(jQuery); // confine scope