corrade-nucleus-nucleons – Rev 20

Subversion Repositories:
Rev:
define( [
        "./core",
        "./var/rnothtmlwhite"
], function( jQuery, rnothtmlwhite ) {

"use strict";

// Convert String-formatted options into Object-formatted ones
function createOptions( options ) {
        var object = {};
        jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
                object[ flag ] = true;
        } );
        return object;
}

/*
 * Create a callback list using the following parameters:
 *
 *      options: an optional list of space-separated options that will change how
 *                      the callback list behaves or a more traditional option object
 *
 * By default a callback list will act like an event callback list and can be
 * "fired" multiple times.
 *
 * Possible options:
 *
 *      once:                   will ensure the callback list can only be fired once (like a Deferred)
 *
 *      memory:                 will keep track of previous values and will call any callback added
 *                                      after the list has been fired right away with the latest "memorized"
 *                                      values (like a Deferred)
 *
 *      unique:                 will ensure a callback can only be added once (no duplicate in the list)
 *
 *      stopOnFalse:    interrupt callings when a callback returns false
 *
 */
jQuery.Callbacks = function( options ) {

        // Convert options from String-formatted to Object-formatted if needed
        // (we check in cache first)
        options = typeof options === "string" ?
                createOptions( options ) :
                jQuery.extend( {}, options );

        var // Flag to know if list is currently firing
                firing,

                // Last fire value for non-forgettable lists
                memory,

                // Flag to know if list was already fired
                fired,

                // Flag to prevent firing
                locked,

                // Actual callback list
                list = [],

                // Queue of execution data for repeatable lists
                queue = [],

                // Index of currently firing callback (modified by add/remove as needed)
                firingIndex = -1,

                // Fire callbacks
                fire = function() {

                        // Enforce single-firing
                        locked = locked || options.once;

                        // Execute callbacks for all pending executions,
                        // respecting firingIndex overrides and runtime changes
                        fired = firing = true;
                        for ( ; queue.length; firingIndex = -1 ) {
                                memory = queue.shift();
                                while ( ++firingIndex < list.length ) {

                                        // Run callback and check for early termination
                                        if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
                                                options.stopOnFalse ) {

                                                // Jump to end and forget the data so .add doesn't re-fire
                                                firingIndex = list.length;
                                                memory = false;
                                        }
                                }
                        }

                        // Forget the data if we're done with it
                        if ( !options.memory ) {
                                memory = false;
                        }

                        firing = false;

                        // Clean up if we're done firing for good
                        if ( locked ) {

                                // Keep an empty list if we have data for future add calls
                                if ( memory ) {
                                        list = [];

                                // Otherwise, this object is spent
                                } else {
                                        list = "";
                                }
                        }
                },

                // Actual Callbacks object
                self = {

                        // Add a callback or a collection of callbacks to the list
                        add: function() {
                                if ( list ) {

                                        // If we have memory from a past run, we should fire after adding
                                        if ( memory && !firing ) {
                                                firingIndex = list.length - 1;
                                                queue.push( memory );
                                        }

                                        ( function add( args ) {
                                                jQuery.each( args, function( _, arg ) {
                                                        if ( jQuery.isFunction( arg ) ) {
                                                                if ( !options.unique || !self.has( arg ) ) {
                                                                        list.push( arg );
                                                                }
                                                        } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {

                                                                // Inspect recursively
                                                                add( arg );
                                                        }
                                                } );
                                        } )( arguments );

                                        if ( memory && !firing ) {
                                                fire();
                                        }
                                }
                                return this;
                        },

                        // Remove a callback from the list
                        remove: function() {
                                jQuery.each( arguments, function( _, arg ) {
                                        var index;
                                        while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
                                                list.splice( index, 1 );

                                                // Handle firing indexes
                                                if ( index <= firingIndex ) {
                                                        firingIndex--;
                                                }
                                        }
                                } );
                                return this;
                        },

                        // Check if a given callback is in the list.
                        // If no argument is given, return whether or not list has callbacks attached.
                        has: function( fn ) {
                                return fn ?
                                        jQuery.inArray( fn, list ) > -1 :
                                        list.length > 0;
                        },

                        // Remove all callbacks from the list
                        empty: function() {
                                if ( list ) {
                                        list = [];
                                }
                                return this;
                        },

                        // Disable .fire and .add
                        // Abort any current/pending executions
                        // Clear all callbacks and values
                        disable: function() {
                                locked = queue = [];
                                list = memory = "";
                                return this;
                        },
                        disabled: function() {
                                return !list;
                        },

                        // Disable .fire
                        // Also disable .add unless we have memory (since it would have no effect)
                        // Abort any pending executions
                        lock: function() {
                                locked = queue = [];
                                if ( !memory && !firing ) {
                                        list = memory = "";
                                }
                                return this;
                        },
                        locked: function() {
                                return !!locked;
                        },

                        // Call all callbacks with the given context and arguments
                        fireWith: function( context, args ) {
                                if ( !locked ) {
                                        args = args || [];
                                        args = [ context, args.slice ? args.slice() : args ];
                                        queue.push( args );
                                        if ( !firing ) {
                                                fire();
                                        }
                                }
                                return this;
                        },

                        // Call all the callbacks with the given arguments
                        fire: function() {
                                self.fireWith( this, arguments );
                                return this;
                        },

                        // To know if the callbacks have already been called at least once
                        fired: function() {
                                return !!fired;
                        }
                };

        return self;
};

return jQuery;
} );