jquery.ba-throttle-debounce.js 10 KB

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