NPL.Prototype.__ElementSet__.FadeOut = function (pCallback)
{
	if ( this._for_all_do ) { this._for_all_do(function(e,c){NPFX_FadeOut(e,c)}, pCallback); }
}

NPL.Prototype.__ElementSet__.FadeIn = function (pElement, pCallback)
{
	if ( this._for_all_do ) { this._for_all_do(function(e,c){NPFX_FadeIn(e,c), pCallback}); }
}

function NPFX_FadeOut ( pElement, pCallback )
{
    if ( this.taskID )
    {
    	var xOpacity = parseFloat(this._element.opacity());
        if ( xOpacity > 0.08 )
        {
        	this._element.opacity(xOpacity - 0.08);
        	//	Guard against infinite loops due to problems adjusting opacity.
        	if ( this._element.opacity() > (xOpacity - 0.08) )
        	{
        		this._element.opacity(0);
        		return 0;
        	}
            return 10;
        }
        this._element.opacity(0);
        return 0;
    }
    else if ( pElement )
    {
        var xTask = NPL.Tasks.NewTask(NPFX_FadeOut);
        xTask._element = NPL.Select(pElement);
        xTask.Name('NPFX_FadeOut');
        if ( pCallback ) { xTask.SetCleanup(pCallback); }
        xTask.Start();
    }
}

function NPFX_FadeIn ( pElement, pCallback )
{
    if ( this.taskID )
    {
        var xOpacity = parseFloat(this._element.opacity());
        if ( xOpacity < 1 )
        {
            this._element.opacity(xOpacity + 0.04);
            //	Same as above -- guard against infinite loops due to problems adjusting opacity.
            if ( this._element.opacity() < (xOpacity + 0.04) )
            {
            	this._element.opacity(1);
            	return 0;
            }
            return 10;
        }
        this._element.opacity(1);
        return 0;
    }
    else if ( pElement )
    {
        var xTask = NPL.Tasks.NewTask(NPFX_FadeIn);
        xTask.Name('NPFX_FadeIn');
        xTask._element = NPL.Select(pElement);
        if ( pCallback ) { xTask.SetCleanup(pCallback); }
        xTask.Start();
    }
}

function Slide_From ( pElement, pCoordinates, pCallback )
//  Slides an element from its current position to pCoordinates (new top-left corner for the element).
//  This function slides an element progressively faster until it reaches its location, and is
//  ideal for moving elements "off" the page.
{
    if ( pElement && pCoordinates )
    {
        var xTask = new TimeTask(Slide_From);
        xTask.SetVar('element', pElement);
        //  Opera apparently has a bug where it doesn't correctly handle saving the 'destination' var as an object.
        //  The best thing about the bug is that it decides to return the same value for destination.x as element.style.left;
        //  I have no clue why. That behavior doesn't make any sense at all. I really love spending all this time
        //  coming up with workarounds for bad browser behavior.
        //  So, anyway, split the pCoordinates parameter into two separate variables here.
        xTask.SetVar('destination-x', pCoordinates.x);
        xTask.SetVar('destination-y', pCoordinates.y);
        xTask.SetVar('iteration', 0);
        if ( pCallback ) { xTask.SetVar('completion', pCallback); }
        xTask.SetCleanup(Slide_From);
        xTask.Run();
        return xTask.id;
    }
    else if ( this.vars )
    {
        if ( this.dying )
        {
            if ( ! isNaN(this.vars['destination-x']) ) { this.vars['element'].style.left = this.vars['destination-x'] + 'px'; }
            if ( ! isNaN(this.vars['destination-y']) ) { this.vars['element'].style.top = this.vars['destination-y'] + 'px'; }
            if ( this.vars['completion'] ) { this.vars['completion'](this.vars['element']); }
        }
        else
        {
            if ( this.vars['iteration'] == 0 )
            {
                //  Calculate the number of iterations of Math.log() required to get the element
                //  from a to b. Then, count down from that number, using the same formula as
                //  the old Slip_ToCenter function.
                var xDeltaFromX = parseInt(NPL.Page.GetElementStyle(this.vars['element'], 'left')) - this.vars['destination-x'];
                this.vars['direction'] = xDeltaFromX < 0 ? 1 : -1;
                xDeltaFromX *= this.vars['direction'] * -1;
                this.vars['iteration'] = 2;
                while ( xDeltaFromX > 2 )
                {
                    this.vars['iteration']++;
                    xDeltaFromX -= xDeltaFromX + (this.vars['direction'] * (xDeltaFromX / Math.log(this.vars['iteration'])));
                }
                this.vars['lastX'] = xDeltaFromX;
                return 10;
            }
            else
            {
                //  This function is not quite right because it won't perfectly return an element
                //  to the position according to the calculations in the loop above.
                //  But it's good enough for now.
                this.vars['lastX'] = this.vars['lastX'] * Math.log(this.vars['iteration'] + 1);
                this.vars['element'].style.left = parseInt(this.vars['element'].style.left) + (this.vars['direction'] * this.vars['lastX']) + 'px';
                this.vars['iteration']--;
                if ( this.vars['iteration'] > 2 ) { return 50; }
                return 0;
            }
        }
    }
}

function Slide_To ( pElement, pCoordinates, pCallback )
//  Slides an element from its current position to pCoordinates (new top-left corner for the element).
//  This function slides an element progressively slower until it reaches its location, and is
//  ideal for moving elements "onto" the page.
{
    if ( pElement && pCoordinates )
    {
        var xTask = new TimeTask(Slide_To);
        xTask.SetVar('element', pElement);
        //  See notes above in Slide_From() regarding destination-x & destination-y.
        xTask.SetVar('destination-x', pCoordinates.x);
        xTask.SetVar('destination-y', pCoordinates.y);
        xTask.SetVar('iteration', 0);
        if ( pCallback ) { xTask.SetVar('completion', pCallback); }
        xTask.SetCleanup(Slide_To);
        xTask.Run();
        return xTask.id;
    }
    else if ( this.vars )
    {
        if ( this.dying )
        {
            if ( ! isNaN(this.vars['destination-x']) ) { this.vars['element'].style.left = this.vars['destination-x'] + 'px'; }
            if ( ! isNaN(this.vars['destination-y']) ) { this.vars['element'].style.top = this.vars['destination-y'] + 'px'; }
            if ( this.vars['completion'] ) { this.vars['completion'](this.vars['element']); }
        }
        else
        {
            var xDeltaFromX = parseInt(NPL.Page.GetElementStyle(this.vars['element'], 'left')) - this.vars['destination-x'];
            if ( this.vars['iteration'] == 0 )
            {
                this.vars['direction'] = xDeltaFromX < 0 ? 1 : -1;
            }
            xDeltaFromX *= this.vars['direction'] * -1;
            if ( xDeltaFromX > 2 )
            {
                this.vars['iteration']++;
                this.vars['element'].style.left = parseInt(this.vars['element'].style.left) + (this.vars['direction'] * (xDeltaFromX / Math.log(this.vars['iteration'] + 5))) + 'px';
                return 50;
            }
            return 0;
        }
    }
}

/*
ElementSet.prototype.FadeOut = FadeOut;
ElementSet.prototype.FadeIn = FadeIn;
*/
