]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/jquery/jquery.throttle-debounce.js
Merge remote-tracking branch 'upstream/pull/3828'
[rails.git] / vendor / assets / jquery / jquery.throttle-debounce.js
1 /*!
2  * jQuery throttle / debounce - v1.1 - 3/7/2010
3  * http://benalman.com/projects/jquery-throttle-debounce-plugin/
4  * 
5  * Copyright (c) 2010 "Cowboy" Ben Alman
6  * Dual licensed under the MIT and GPL licenses.
7  * http://benalman.com/about/license/
8  */
9
10 // Script: jQuery throttle / debounce: Sometimes, less is more!
11 //
12 // *Version: 1.1, Last updated: 3/7/2010*
13 // 
14 // Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
15 // GitHub       - http://github.com/cowboy/jquery-throttle-debounce/
16 // Source       - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
17 // (Minified)   - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
18 // 
19 // About: License
20 // 
21 // Copyright (c) 2010 "Cowboy" Ben Alman,
22 // Dual licensed under the MIT and GPL licenses.
23 // http://benalman.com/about/license/
24 // 
25 // About: Examples
26 // 
27 // These working examples, complete with fully commented code, illustrate a few
28 // ways in which this plugin can be used.
29 // 
30 // Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
31 // Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
32 // 
33 // About: Support and Testing
34 // 
35 // Information about what version or versions of jQuery this plugin has been
36 // tested with, what browsers it has been tested in, and where the unit tests
37 // reside (so you can test it yourself).
38 // 
39 // jQuery Versions - none, 1.3.2, 1.4.2
40 // Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
41 // Unit Tests      - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
42 // 
43 // About: Release History
44 // 
45 // 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
46 //       executed later than they should. Reworked a fair amount of internal
47 //       logic as well.
48 // 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
49 //       from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
50 //       no_trailing throttle parameter and debounce functionality.
51 // 
52 // Topic: Note for non-jQuery users
53 // 
54 // jQuery isn't actually required for this plugin, because nothing internal
55 // uses any jQuery methods or properties. jQuery is just used as a namespace
56 // under which these methods can exist.
57 // 
58 // Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
59 // when this plugin is loaded, the method described below will be created in
60 // the `Cowboy` namespace. Usage will be exactly the same, but instead of
61 // $.method() or jQuery.method(), you'll need to use Cowboy.method().
62
63 (function(window,undefined){
64   '$:nomunge'; // Used by YUI compressor.
65   
66   // Since jQuery really isn't required for this plugin, use `jQuery` as the
67   // namespace only if it already exists, otherwise use the `Cowboy` namespace,
68   // creating it if necessary.
69   var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
70     
71     // Internal method reference.
72     jq_throttle;
73   
74   // Method: jQuery.throttle
75   // 
76   // Throttle execution of a function. Especially useful for rate limiting
77   // execution of handlers on events like resize and scroll. If you want to
78   // rate-limit execution of a function to a single time, see the
79   // <jQuery.debounce> method.
80   // 
81   // In this visualization, | is a throttled-function call and X is the actual
82   // callback execution:
83   // 
84   // > Throttled with `no_trailing` specified as false or unspecified:
85   // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
86   // > X    X    X    X    X    X        X    X    X    X    X    X
87   // > 
88   // > Throttled with `no_trailing` specified as true:
89   // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
90   // > X    X    X    X    X             X    X    X    X    X
91   // 
92   // Usage:
93   // 
94   // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
95   // > 
96   // > jQuery('selector').bind( 'someevent', throttled );
97   // > jQuery('selector').unbind( 'someevent', throttled );
98   // 
99   // This also works in jQuery 1.4+:
100   // 
101   // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
102   // > jQuery('selector').unbind( 'someevent', callback );
103   // 
104   // Arguments:
105   // 
106   //  delay - (Number) A zero-or-greater delay in milliseconds. For event
107   //    callbacks, values around 100 or 250 (or even higher) are most useful.
108   //  no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
109   //    true, callback will only execute every `delay` milliseconds while the
110   //    throttled-function is being called. If no_trailing is false or
111   //    unspecified, callback will be executed one final time after the last
112   //    throttled-function call. (After the throttled-function has not been
113   //    called for `delay` milliseconds, the internal counter is reset)
114   //  callback - (Function) A function to be executed after delay milliseconds.
115   //    The `this` context and all arguments are passed through, as-is, to
116   //    `callback` when the throttled-function is executed.
117   // 
118   // Returns:
119   // 
120   //  (Function) A new, throttled, function.
121   
122   $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
123     // After wrapper has stopped being called, this timeout ensures that
124     // `callback` is executed at the proper times in `throttle` and `end`
125     // debounce modes.
126     var timeout_id,
127       
128       // Keep track of the last time `callback` was executed.
129       last_exec = 0;
130     
131     // `no_trailing` defaults to falsy.
132     if ( typeof no_trailing !== 'boolean' ) {
133       debounce_mode = callback;
134       callback = no_trailing;
135       no_trailing = undefined;
136     }
137     
138     // The `wrapper` function encapsulates all of the throttling / debouncing
139     // functionality and when executed will limit the rate at which `callback`
140     // is executed.
141     function wrapper() {
142       var that = this,
143         elapsed = +new Date() - last_exec,
144         args = arguments;
145       
146       // Execute `callback` and update the `last_exec` timestamp.
147       function exec() {
148         last_exec = +new Date();
149         callback.apply( that, args );
150       };
151       
152       // If `debounce_mode` is true (at_begin) this is used to clear the flag
153       // to allow future `callback` executions.
154       function clear() {
155         timeout_id = undefined;
156       };
157       
158       if ( debounce_mode && !timeout_id ) {
159         // Since `wrapper` is being called for the first time and
160         // `debounce_mode` is true (at_begin), execute `callback`.
161         exec();
162       }
163       
164       // Clear any existing timeout.
165       timeout_id && clearTimeout( timeout_id );
166       
167       if ( debounce_mode === undefined && elapsed > delay ) {
168         // In throttle mode, if `delay` time has been exceeded, execute
169         // `callback`.
170         exec();
171         
172       } else if ( no_trailing !== true ) {
173         // In trailing throttle mode, since `delay` time has not been
174         // exceeded, schedule `callback` to execute `delay` ms after most
175         // recent execution.
176         // 
177         // If `debounce_mode` is true (at_begin), schedule `clear` to execute
178         // after `delay` ms.
179         // 
180         // If `debounce_mode` is false (at end), schedule `callback` to
181         // execute after `delay` ms.
182         timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
183       }
184     };
185     
186     // Set the guid of `wrapper` function to the same of original callback, so
187     // it can be removed in jQuery 1.4+ .unbind or .die by using the original
188     // callback as a reference.
189     if ( $.guid ) {
190       wrapper.guid = callback.guid = callback.guid || $.guid++;
191     }
192     
193     // Return the wrapper function.
194     return wrapper;
195   };
196   
197   // Method: jQuery.debounce
198   // 
199   // Debounce execution of a function. Debouncing, unlike throttling,
200   // guarantees that a function is only executed a single time, either at the
201   // very beginning of a series of calls, or at the very end. If you want to
202   // simply rate-limit execution of a function, see the <jQuery.throttle>
203   // method.
204   // 
205   // In this visualization, | is a debounced-function call and X is the actual
206   // callback execution:
207   // 
208   // > Debounced with `at_begin` specified as false or unspecified:
209   // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
210   // >                          X                                 X
211   // > 
212   // > Debounced with `at_begin` specified as true:
213   // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
214   // > X                                 X
215   // 
216   // Usage:
217   // 
218   // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
219   // > 
220   // > jQuery('selector').bind( 'someevent', debounced );
221   // > jQuery('selector').unbind( 'someevent', debounced );
222   // 
223   // This also works in jQuery 1.4+:
224   // 
225   // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
226   // > jQuery('selector').unbind( 'someevent', callback );
227   // 
228   // Arguments:
229   // 
230   //  delay - (Number) A zero-or-greater delay in milliseconds. For event
231   //    callbacks, values around 100 or 250 (or even higher) are most useful.
232   //  at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
233   //    unspecified, callback will only be executed `delay` milliseconds after
234   //    the last debounced-function call. If at_begin is true, callback will be
235   //    executed only at the first debounced-function call. (After the
236   //    throttled-function has not been called for `delay` milliseconds, the
237   //    internal counter is reset)
238   //  callback - (Function) A function to be executed after delay milliseconds.
239   //    The `this` context and all arguments are passed through, as-is, to
240   //    `callback` when the debounced-function is executed.
241   // 
242   // Returns:
243   // 
244   //  (Function) A new, debounced, function.
245   
246   $.debounce = function( delay, at_begin, callback ) {
247     return callback === undefined
248       ? jq_throttle( delay, at_begin, false )
249       : jq_throttle( delay, callback, at_begin !== false );
250   };
251   
252 })(this);