226 lines
7.4 KiB
JavaScript
226 lines
7.4 KiB
JavaScript
|
/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
|
|||
|
* Dual licensed under the MIT (MIT_LICENSE.txt)
|
|||
|
* and GPL Version 2 (GPL_LICENSE.txt) licenses.
|
|||
|
*
|
|||
|
* Version: 1.1.1
|
|||
|
* Requires jQuery 1.3+
|
|||
|
* Docs: http://docs.jquery.com/Plugins/livequery
|
|||
|
*/
|
|||
|
|
|||
|
(function ($) {
|
|||
|
|
|||
|
$.extend($.fn, {
|
|||
|
livequery: function (type, fn, fn2) {
|
|||
|
var self = this, q;
|
|||
|
|
|||
|
// Handle different call patterns
|
|||
|
if ($.isFunction(type))
|
|||
|
fn2 = fn, fn = type, type = undefined;
|
|||
|
|
|||
|
// See if Live Query already exists
|
|||
|
$.each($.livequery.queries, function (i, query) {
|
|||
|
if (self.selector == query.selector && self.context == query.context &&
|
|||
|
type == query.type && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid))
|
|||
|
// Found the query, exit the each loop
|
|||
|
return (q = query) && false;
|
|||
|
});
|
|||
|
|
|||
|
// Create new Live Query if it wasn't found
|
|||
|
q = q || new $.livequery(this.selector, this.context, type, fn, fn2);
|
|||
|
|
|||
|
// Make sure it is running
|
|||
|
q.stopped = false;
|
|||
|
|
|||
|
// Run it immediately for the first time
|
|||
|
q.run();
|
|||
|
|
|||
|
// Contnue the chain
|
|||
|
return this;
|
|||
|
},
|
|||
|
|
|||
|
expire: function (type, fn, fn2) {
|
|||
|
var self = this;
|
|||
|
|
|||
|
// Handle different call patterns
|
|||
|
if ($.isFunction(type))
|
|||
|
fn2 = fn, fn = type, type = undefined;
|
|||
|
|
|||
|
// Find the Live Query based on arguments and stop it
|
|||
|
$.each($.livequery.queries, function (i, query) {
|
|||
|
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)
|
|||
|
$.livequery.stop(query.id);
|
|||
|
});
|
|||
|
|
|||
|
// Continue the chain
|
|||
|
return this;
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
$.livequery = function (selector, context, type, fn, fn2) {
|
|||
|
this.selector = selector;
|
|||
|
this.context = context;
|
|||
|
this.type = type;
|
|||
|
this.fn = fn;
|
|||
|
this.fn2 = fn2;
|
|||
|
this.elements = [];
|
|||
|
this.stopped = false;
|
|||
|
|
|||
|
// The id is the index of the Live Query in $.livequery.queries
|
|||
|
this.id = $.livequery.queries.push(this) - 1;
|
|||
|
|
|||
|
// Mark the functions for matching later on
|
|||
|
fn.$lqguid = fn.$lqguid || $.livequery.guid++;
|
|||
|
if (fn2) fn2.$lqguid = fn2.$lqguid || $.livequery.guid++;
|
|||
|
|
|||
|
// Return the Live Query
|
|||
|
return this;
|
|||
|
};
|
|||
|
|
|||
|
$.livequery.prototype = {
|
|||
|
stop: function () {
|
|||
|
var query = this;
|
|||
|
|
|||
|
if (this.type)
|
|||
|
// Unbind all bound events
|
|||
|
this.elements.unbind(this.type, this.fn);
|
|||
|
else if (this.fn2)
|
|||
|
// Call the second function for all matched elements
|
|||
|
this.elements.each(function (i, el) {
|
|||
|
query.fn2.apply(el);
|
|||
|
});
|
|||
|
|
|||
|
// Clear out matched elements
|
|||
|
this.elements = [];
|
|||
|
|
|||
|
// Stop the Live Query from running until restarted
|
|||
|
this.stopped = true;
|
|||
|
},
|
|||
|
|
|||
|
run: function () {
|
|||
|
// Short-circuit if stopped
|
|||
|
if (this.stopped) return;
|
|||
|
var query = this;
|
|||
|
|
|||
|
var oEls = this.elements,
|
|||
|
els = $(this.selector, this.context),
|
|||
|
nEls = els.not(oEls);
|
|||
|
|
|||
|
// Set elements to the latest set of matched elements
|
|||
|
this.elements = els;
|
|||
|
|
|||
|
if (this.type) {
|
|||
|
// Bind events to newly matched elements
|
|||
|
nEls.bind(this.type, this.fn);
|
|||
|
|
|||
|
// Unbind events to elements no longer matched
|
|||
|
if (oEls.length > 0)
|
|||
|
$.each(oEls, function (i, el) {
|
|||
|
if ($.inArray(el, els) < 0)
|
|||
|
$.event.remove(el, query.type, query.fn);
|
|||
|
});
|
|||
|
}
|
|||
|
else {
|
|||
|
// Call the first function for newly matched elements
|
|||
|
nEls.each(function () {
|
|||
|
query.fn.apply(this);
|
|||
|
});
|
|||
|
|
|||
|
// Call the second function for elements no longer matched
|
|||
|
if (this.fn2 && oEls.length > 0)
|
|||
|
$.each(oEls, function (i, el) {
|
|||
|
if ($.inArray(el, els) < 0)
|
|||
|
query.fn2.apply(el);
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
$.extend($.livequery, {
|
|||
|
guid: 0,
|
|||
|
queries: [],
|
|||
|
queue: [],
|
|||
|
running: false,
|
|||
|
timeout: null,
|
|||
|
|
|||
|
checkQueue: function () {
|
|||
|
if ($.livequery.running && $.livequery.queue.length) {
|
|||
|
var length = $.livequery.queue.length;
|
|||
|
// Run each Live Query currently in the queue
|
|||
|
while (length--)
|
|||
|
$.livequery.queries[$.livequery.queue.shift()].run();
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
pause: function () {
|
|||
|
// Don't run anymore Live Queries until restarted
|
|||
|
$.livequery.running = false;
|
|||
|
},
|
|||
|
|
|||
|
play: function () {
|
|||
|
// Restart Live Queries
|
|||
|
$.livequery.running = true;
|
|||
|
// Request a run of the Live Queries
|
|||
|
$.livequery.run();
|
|||
|
},
|
|||
|
|
|||
|
registerPlugin: function () {
|
|||
|
$.each(arguments, function (i, n) {
|
|||
|
// Short-circuit if the method doesn't exist
|
|||
|
if (!$.fn[n]) return;
|
|||
|
|
|||
|
// Save a reference to the original method
|
|||
|
var old = $.fn[n];
|
|||
|
|
|||
|
// Create a new method
|
|||
|
$.fn[n] = function () {
|
|||
|
// Call the original method
|
|||
|
var r = old.apply(this, arguments);
|
|||
|
|
|||
|
// Request a run of the Live Queries
|
|||
|
$.livequery.run();
|
|||
|
|
|||
|
// Return the original methods result
|
|||
|
return r;
|
|||
|
}
|
|||
|
});
|
|||
|
},
|
|||
|
|
|||
|
run: function (id) {
|
|||
|
if (id != undefined) {
|
|||
|
// Put the particular Live Query in the queue if it doesn't already exist
|
|||
|
if ($.inArray(id, $.livequery.queue) < 0)
|
|||
|
$.livequery.queue.push(id);
|
|||
|
}
|
|||
|
else
|
|||
|
// Put each Live Query in the queue if it doesn't already exist
|
|||
|
$.each($.livequery.queries, function (id) {
|
|||
|
if ($.inArray(id, $.livequery.queue) < 0)
|
|||
|
$.livequery.queue.push(id);
|
|||
|
});
|
|||
|
|
|||
|
// Clear timeout if it already exists
|
|||
|
if ($.livequery.timeout) clearTimeout($.livequery.timeout);
|
|||
|
// Create a timeout to check the queue and actually run the Live Queries
|
|||
|
$.livequery.timeout = setTimeout($.livequery.checkQueue, 20);
|
|||
|
},
|
|||
|
|
|||
|
stop: function (id) {
|
|||
|
if (id != undefined)
|
|||
|
// Stop are particular Live Query
|
|||
|
$.livequery.queries[id].stop();
|
|||
|
else
|
|||
|
// Stop all Live Queries
|
|||
|
$.each($.livequery.queries, function (id) {
|
|||
|
$.livequery.queries[id].stop();
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
// Register core DOM manipulation methods
|
|||
|
$.livequery.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove', 'html');
|
|||
|
|
|||
|
// Run Live Queries when the Document is ready
|
|||
|
$(function () { $.livequery.play(); });
|
|||
|
|
|||
|
})(jQuery);
|