jquery.livequery.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
  2. * Dual licensed under the MIT (MIT_LICENSE.txt)
  3. * and GPL Version 2 (GPL_LICENSE.txt) licenses.
  4. *
  5. * Version: 1.1.1
  6. * Requires jQuery 1.3+
  7. * Docs: http://docs.jquery.com/Plugins/livequery
  8. */
  9. (function($) {
  10. $.extend($.fn, {
  11. livequery: function(type, fn, fn2) {
  12. var self = this, q;
  13. // Handle different call patterns
  14. if ($.isFunction(type))
  15. fn2 = fn, fn = type, type = undefined;
  16. // See if Live Query already exists
  17. $.each($.livequery.queries, function(i, query) {
  18. if (self.selector == query.selector && self.context == query.context && type == query.type && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid))
  19. // Found the query, exit the each loop
  20. return ( q = query) && false;
  21. });
  22. // Create new Live Query if it wasn't found
  23. q = q || new $.livequery(this.selector, this.context, type, fn, fn2);
  24. // Make sure it is running
  25. q.stopped = false;
  26. // Run it immediately for the first time
  27. q.run();
  28. // Contnue the chain
  29. return this;
  30. },
  31. expire: function(type, fn, fn2) {
  32. var self = this;
  33. // Handle different call patterns
  34. if ($.isFunction(type))
  35. fn2 = fn, fn = type, type = undefined;
  36. // Find the Live Query based on arguments and stop it
  37. $.each($.livequery.queries, function(i, query) {
  38. if (self.selector == query.selector && self.context == query.context && (!type || type == query.type) && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) && !this.stopped)
  39. $.livequery.stop(query.id);
  40. });
  41. // Continue the chain
  42. return this;
  43. }
  44. });
  45. $.livequery = function(selector, context, type, fn, fn2) {
  46. this.selector = selector;
  47. this.context = context;
  48. this.type = type;
  49. this.fn = fn;
  50. this.fn2 = fn2;
  51. this.elements = [];
  52. this.stopped = false;
  53. // The id is the index of the Live Query in $.livequery.queries
  54. this.id = $.livequery.queries.push(this) - 1;
  55. // Mark the functions for matching later on
  56. fn.$lqguid = fn.$lqguid || $.livequery.guid++;
  57. if (fn2)
  58. fn2.$lqguid = fn2.$lqguid || $.livequery.guid++;
  59. // Return the Live Query
  60. return this;
  61. };
  62. $.livequery.prototype = {
  63. stop: function() {
  64. var query = this;
  65. if (this.type)
  66. // Unbind all bound events
  67. this.elements.unbind(this.type, this.fn);
  68. else if (this.fn2)
  69. // Call the second function for all matched elements
  70. this.elements.each(function(i, el) {
  71. query.fn2.apply(el);
  72. });
  73. // Clear out matched elements
  74. this.elements = [];
  75. // Stop the Live Query from running until restarted
  76. this.stopped = true;
  77. },
  78. run: function() {
  79. // Short-circuit if stopped
  80. if (this.stopped)
  81. return;
  82. var query = this;
  83. var oEls = this.elements, els = $(this.selector, this.context), nEls = els.not(oEls);
  84. // Set elements to the latest set of matched elements
  85. this.elements = els;
  86. if (this.type) {
  87. // Bind events to newly matched elements
  88. nEls.bind(this.type, this.fn);
  89. // Unbind events to elements no longer matched
  90. if (oEls.length > 0)
  91. $.each(oEls, function(i, el) {
  92. if ($.inArray(el, els) < 0)
  93. $.event.remove(el, query.type, query.fn);
  94. });
  95. }
  96. else {
  97. // Call the first function for newly matched elements
  98. nEls.each(function() {
  99. query.fn.apply(this);
  100. });
  101. // Call the second function for elements no longer matched
  102. if (this.fn2 && oEls.length > 0)
  103. $.each(oEls, function(i, el) {
  104. if ($.inArray(el, els) < 0)
  105. query.fn2.apply(el);
  106. });
  107. }
  108. }
  109. };
  110. $.extend($.livequery, {
  111. guid: 0,
  112. queries: [],
  113. queue: [],
  114. running: false,
  115. timeout: null,
  116. checkQueue: function() {
  117. if ($.livequery.running && $.livequery.queue.length) {
  118. var length = $.livequery.queue.length;
  119. // Run each Live Query currently in the queue
  120. while (length--)
  121. $.livequery.queries[ $.livequery.queue.shift()].run();
  122. }
  123. },
  124. pause: function() {
  125. // Don't run anymore Live Queries until restarted
  126. $.livequery.running = false;
  127. },
  128. play: function() {
  129. // Restart Live Queries
  130. $.livequery.running = true;
  131. // Request a run of the Live Queries
  132. $.livequery.run();
  133. },
  134. registerPlugin: function() {
  135. $.each(arguments, function(i, n) {
  136. // Short-circuit if the method doesn't exist
  137. if (!$.fn[n])
  138. return;
  139. // Save a reference to the original method
  140. var old = $.fn[n];
  141. // Create a new method
  142. $.fn[n] = function() {
  143. // Call the original method
  144. var r = old.apply(this, arguments);
  145. // Request a run of the Live Queries
  146. $.livequery.run();
  147. // Return the original methods result
  148. return r;
  149. }
  150. });
  151. },
  152. run: function(id) {
  153. if (id != undefined) {
  154. // Put the particular Live Query in the queue if it doesn't already exist
  155. if ($.inArray(id, $.livequery.queue) < 0)
  156. $.livequery.queue.push(id);
  157. }
  158. else
  159. // Put each Live Query in the queue if it doesn't already exist
  160. $.each($.livequery.queries, function(id) {
  161. if ($.inArray(id, $.livequery.queue) < 0)
  162. $.livequery.queue.push(id);
  163. });
  164. // Clear timeout if it already exists
  165. if ($.livequery.timeout)
  166. clearTimeout($.livequery.timeout);
  167. // Create a timeout to check the queue and actually run the Live Queries
  168. $.livequery.timeout = setTimeout($.livequery.checkQueue, 20);
  169. },
  170. stop: function(id) {
  171. if (id != undefined)
  172. // Stop are particular Live Query
  173. $.livequery.queries[id].stop();
  174. else
  175. // Stop all Live Queries
  176. $.each($.livequery.queries, function(id) {
  177. $.livequery.queries[id].stop();
  178. });
  179. }
  180. });
  181. // Register core DOM manipulation methods
  182. $.livequery.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove', 'html');
  183. // Run Live Queries when the Document is ready
  184. $(function() {
  185. $.livequery.play();
  186. });
  187. })(jQuery);