Skip to content

Instantly share code, notes, and snippets.

@maggiben
Created August 17, 2013 04:30
Show Gist options
  • Save maggiben/6255273 to your computer and use it in GitHub Desktop.
Save maggiben/6255273 to your computer and use it in GitHub Desktop.
(function (root, factory) {
"use strict";
if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory(require('jquery'), require('debug'));
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery', 'debug'], factory);
} else {
// Browser globals (root is window)
root.QueueManager = factory(root.jquery, root.debug);
}
}(this, function (jquery, debug) {
"use strict";
var QueueManager = (function() {
function QueueManager(settings) {
////////////////////////////////////////////////////////////////////
// Constructor //
////////////////////////////////////////////////////////////////////
var _self = this;
this.version = '1.0';
var defaults = {
delay: 100,
batch: 1,
callback: null,
complete: null,
paused: false,
queue: []
};
// Merge options
this.options = jquery.extend({}, defaults, settings);
// The actual queue.
this.queue = this.options.queue;
this.paused = this.options.paused;
this.recent = [];
this.timeout_id;
this.cleared;
// If queue isn't explicitly paused, start it.
if(!this.paused) {
this.start();
}
}
QueueManager.prototype.each = function(args) {
var that = this;
this.onEach = args;
return that;
};
QueueManager.prototype.complete = function(args) {
var that = this;
that.onComplete = args;
return that;
}
// Method: QueueManager.add
//
// Add a single item onto the queue. If you want to add multiple items onto
// the queue individually, use <QueueManager.addEach>. If the queue was empty and
// not paused, processing will resume immediately.
//
// Usage:
//
// > QueueManager.add( item [, priority ] );
//
// Arguments:
//
// item - (Anything) A single item to add to the queue.
// priority - (Boolean) If true, the item is added to the front of the
// queue, otherwise the item is added to the end of the queue. Defaults
// to false.
//
// Returns:
//
// (Number) The length of the queue, after the item has been added.
QueueManager.prototype.add = function( item, priority ) {
var that = this;
return that.addEach( [ item ], priority );
};
// Method: QueueManager.addEach
//
// Add multiple items onto the queue, individually. If you want to add a
// single item onto the queue, use <QueueManager.add>. If the queue was empty and
// not paused, processing will resume immediately.
//
// Usage:
//
// > QueueManager.addEach( items [, priority ] );
//
// Arguments:
//
// items - (Array) An array of items to add to the queue.
// priority - (Boolean) If true, the items are added to the front of the
// queue, otherwise the items are added to the end of the queue. Defaults
// to false.
//
// Returns:
//
// (Number) The length of the queue, after the items have been added.
QueueManager.prototype.addEach = function( items, priority ) {
var that = this;
if ( items ) {
// Unset "cleared" status.
that.cleared = false;
// Push all items, individually, onto the queue. If priority is true, send
// them to the beginning, otherwise, send them to the end.
that.queue = priority
? items.concat( that.queue )
: that.queue.concat( items );
// If queue isn't explicitly paused, restart it.
if(!that.paused) {
that.start();
}
}
return that//.size();
};
// Method: QueueManager.start
//
// Start a currently paused queue. If an empty queue is started, it will
// automatically start processing items as soon as they are added.
//
// Usage:
//
// > QueueManager.start();
//
// Returns:
//
// Nothing.
QueueManager.prototype.start = function() {
// Flag queue as un-paused.
var that = this;
this.paused = false;
if ( this.size() && !this.timeout_id && !this.recent.length ) {
(function loopy(){
var delay = that.options.delay;
var batch = that.options.batch;
var complete = that.options.complete;
var callback = that.options.callback;
// Clear timeout_id.
that.stop();
// If queue is empty, call the "complete" method if it exists and quit.
if ( !that.size() ) {
that.cleared = true;
complete && complete.call( self );
that.onComplete && that.onComplete.call( self );
return;
}
// Queue has items, so shift off the first `batch` items.
that.recent = that.queue.splice( 0, batch );
// If "callback" method returns true, unshift the queue items for
// another attempt.
if ( that.onEach && that.onEach.call( self, batch === 1 ? that.recent[0] : that.recent ) === true ) {
that.queue = that.recent.concat( that.queue );
that.recent = [];
}
else if ( callback && callback.call( self, batch === 1 ? that.recent[0] : that.recent ) === true ) {
that.queue = that.recent.concat( that.queue );
that.recent = [];
}
// Repeatedly loop if the delay is a number >= 0, otherwise wait for a
// $.jqmqNext() call.
if ( typeof delay === 'number' && delay >= 0 ) {
that.recent = [];
that.timeout_id = setTimeout( loopy, delay );
}
})();
}
};
// Method: QueueManager.next
//
// Intended to be called from within the <jQuery.jqmq> callback, this method
// will continue a queue with a delay of -1. This is most useful for queues
// of asynchronous-but-serial actions, like AJAX requests that must execute
// in order, but not overlap.
//
// Usage:
//
// > QueueManager.next( [ retry ] );
//
// Arguments:
//
// retry - (Boolean) If true, the queue item(s) will be re-added back to
// the front of the queue to be retried on the next queue execution.
//
// Returns:
//
// Nothing.
QueueManager.prototype.next = function( retry ) {
var complete = this.options.complete;
// If retry is true, unshift the most recent items for another attempt.
if ( retry ) {
this.queue = this.recent.concat( this.queue );
}
// Reset the recent items list.
this.recent = [];
// If queue is empty (but not from calling .clear), call the "complete"
// method if it exists, otherwise continue processing the queue (if not
// paused).
if ( this.size() ) {
this.paused || this.start();
} else if ( !this.cleared ) {
this.cleared = true;
complete && complete.call( self );
}
};
// Method: QueueManager.clear
//
// Clear a queue completely. The paused/started status of the queue is
// unchanged.
//
// Usage:
//
// > QueueManager.clear();
//
// Returns:
//
// (Array) The previous queue contents.
QueueManager.prototype.clear = function() {
var that = this;
var result = that.queue;
// Stop the queue if it is running.
that.stop();
// Clear the queue.
that.queue = [];
that.cleared = true;
// Reset the recent items list.
that.recent = [];
// Return the previous queue, in case it's needed for some reason.
return result;
};
// Method: QueueManager.pause
//
// Pause a currently running queue. A paused but empty queue will need to be
// manually restarted with <QueueManager.start> even after new items are added.
//
// Usage:
//
// > QueueManager.pause();
//
// Returns:
//
// Nothing.
QueueManager.prototype.pause = function() {
var that = this;
// Stop the queue if it is running.
that.stop();
// Flag it as paused.
that.paused = true;
return that;
};
// Method: QueueManager.update
//
// Update an existing queue's options.
//
// Usage:
//
// > QueueManager.update( options );
//
// Arguments:
//
// options - (Object) An object containing options specific to this queue.
//
// Options:
//
// The delay, batch, callback and complete options from <jQuery.jqmq> can
// be updated. The queue and paused state can be changed using the other
// QueueManager methods.
//
// Returns:
//
// Nothing.
QueueManager.prototype.update = function( opts ) {
var that = this;
$.extend( that.options, opts );
};
// Method: QueueManager.size
//
// Get the current queue length.
//
// Usage:
//
// > QueueManager.size();
//
// Returns:
//
// (Number) The length of the queue.
QueueManager.prototype.size = function() {
var that = this;
return that.queue.length;
};
// Method: QueueManager.indexOf
//
// Get the current index in the queue of the passed item.
//
// Usage:
//
// > QueueManager.indexOf( item );
//
// Arguments:
//
// item - (Anything) An item to test the index of.
//
// Returns:
//
// (Number) The index of the passed item in the queue. Returns -1 if not
// found.
QueueManager.prototype.indexOf = function( item ) {
var that = this;
return that.queue.indexOf(item);
};
// Stop a running queue, optionally flagging it as paused.
QueueManager.prototype.stop = function() {
var that = this;
that.timeout_id && clearTimeout(that.timeout_id);
that.timeout_id = undefined;
};
////////////////////////////////////////////////////////////////////////
// Get module version number //
////////////////////////////////////////////////////////////////////////
QueueManager.prototype.getVersion = function() {
return this.version;
};
return QueueManager;
}());
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
return QueueManager;
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment