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