Source: js/library.classes.js

/** @class
    @readonly
    @desc     Instantiates a controller for a new loading spinner overlay within desired context element.
    
    @arg      {String|Element|jQuery} [context='body'] - Container reference or query selector to create spinner within.
    @arg      {Boolean}               [opaque=false]   - Whether to completely obscure content behind spinner.
    @arg      {Function}              [callback]       - Function to call after spinner completely fades in.
*/
var SpinnerClass = function(context, opaque, callback)
{
    /* properties */
    
    /** @member   {Boolean} SpinnerClass#opaque
        @readonly
        @desc     Whether {@link SpinnerClass#$element} completely obscures content behind it.
        @see      {@link SpinnerClass}
    */
    this.opaque = opaque || false;
    
    /** @member   {jQuery} SpinnerClass#$context
        @readonly
        @desc     Element containing spinner layer.
        @see      {@link SpinnerClass}
    */
    this.$context = (typeof context === 'string' ? $(context) : context) || $('body');
    
    /** @member   {jQuery} SpinnerClass#$element
        @readonly
        @desc     Layer containing spinner graphic.
        @see      {@link SpinnerClass}
    */
    this.$element = null;
    
    var instance = this,
        callback = callback || function () {};
    
    /* methods */
    
    /** @method   SpinnerClass#show
        @readonly
        @desc     Reveals spinner layer.
        @arg      {Function} callback - Function to call after layer is revealed.
    */
    this.show = function (callback)
    {
        this.$element = $(templates.spinner({'opaque': this.opaque}));
        callback      = callback || function () {};
        
        $('body').append(this.$element);
        
        this.$element.fadeIn(
        {
            'duration': 250,
            'easing'  : 'easeInOutCubic',
            'done'    : callback
        });
    };
    
    /** @method   SpinnerClass#hide
        @readonly
        @desc     Conceals spinner layer.
        @arg      {Function} callback - Function to call after layer is concealed.
    */
    this.hide = function (callback)
    {
        this.$element.fadeOut(
        {
            'duration': 250,
            'easing'  : 'easeInOutCubic',
            'done'    : function ()
            {
                instance.$element.remove();
                callback && callback();
            }
        });
    };
    
    /** @method   SpinnerClass#remove
        @readonly
        @desc     Destroys spinner layer.
        @todo     {@link SpinnerClass#hide} already removes, so this is redundant.
    */
    this.remove = function ()
    {
        this.hide(function () { instance.$element.remove(); });
    };
    
    /* construct */
    
    this.show(callback);
    
    log(L_INFO, 'SpinnerClass', 'new instance');
};



/** @class
    @readonly
    @desc     Instantiates a timer object, useful for benchmarking.
    
    @arg      {String|Element|jQuery} [context='body'] - Container reference or query selector to create spinner within.
    @arg      {Boolean}               [opaque=false]   - Whether to completely hide content behind spinner.
    @arg      {Function}              [callback]       - Function to call after spinner completely fades in.
*/
var TimerClass = function ()
{
    /* properties */
    
    var timestamp = function () { return (new Date()).getTime(); },
        value     = 0;
    
    /* methods */
    
    /** @method   TimerClass#started
        @readonly
        @desc     Discloses when timer was instantiated/reset.
        @returns  {Number} Integer timestamp (ms).
    */
    this.started  = function ()           { return value; };
    
    /** @method   TimerClass#elapsed
        @readonly
        @desc     Discloses duration since timer was instantiated/reset.
        @returns  {Number} Integer duration (ms).
    */
    this.elapsed  = function (showUnits)  { return (timestamp() - value) + (showUnits ? 'ms' : ''); };
    
    /** @method   TimerClass#reset
        @readonly
        @desc     Adjusts instantiation time to now.
        @returns  {Number} Integer timestamp (ms).
    */
    this.reset    = function ()           { value = timestamp(); return this.started(); };
    
    /* construct */
    
    this.reset();
};