Merge "Improve docs for Title::getInternalURL/getCanonicalURL"
[lhc/web/wiklou.git] / resources / lib / jquery.throttle-debounce / jquery.ba-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);