// © rod morelos | rodmorelos@msn.com
// keep these two lines and you're free to use this code

// timer variables
createObjectById.prototype.slideTimer = 0;
createObjectById.prototype.resizeTimer = 0;
createObjectById.prototype.fadeTimer = 0;

// slideTo(); slides a layer from it's current position to another point over a specified time period.
// x, y     = destination coordinates in pixels
// duration = how long in milliseconds to do the animation for
// acc      = coefficient of accelleration: 1 = accelerate; 0 = linear; -1 = deccelerate
//            (if acc > 1 then it will go backwards before heading towards destination)
// fn       = execute onSlideEnd() function when animation has finished? true or false.
createObjectById.prototype.slideTo = function(x, y, duration, acc, fn)
{
        clearInterval(this.slideTimer);
        if (!acc) acc = 0;
        if (!fn) fn = false;
        var startTime = new Date().getTime();
        var endTime = startTime + duration;
        this.slideTimer = setInterval('createObjectById.registry[' + this.i + '].slide(' + this.x + ', ' + this.y + ', ' + x + ', ' + y + ', ' + acc + ', ' + startTime + ', ' + endTime + ', ' + fn + ')', 10);
}

createObjectById.prototype.onSlide = new Function();
createObjectById.prototype.onSlideEnd = new Function();

createObjectById.prototype.slide = function(startX, startY, endX, endY, acc, startTime, endTime, fn)
{
        var currentTime = new Date().getTime();
        if (currentTime < endTime)
        {
                var percent = (currentTime - startTime) / (endTime - startTime);
                var c1 = new createObjectById.coord(1, 1);
                var c2 = new createObjectById.coord(0, 0);
                if (acc != 0) var c3 = new createObjectById.coord(0.5 + (acc / 2), 0.5 - (acc / 2)); else c3 = null;
                var pos = createObjectById.getBezier(percent, c1, c2, c3);
                var x = ((endX - startX) * pos.y) + startX;
                var y = ((endY - startY) * pos.y) + startY;
                this.moveTo(x, y);
                this.onSlide(x, y);
        }
        else
        {
                clearInterval(this.slideTimer);
                this.moveTo(endX, endY);
                this.onSlide(endX, endY);
                if (fn) this.onSlideEnd(endX, endY);
        }
}

// bezierSlide(); like slideTo but instead of a straight line it follows a bezier curve
// x, y     = destination coordinates in pixels
// c1x, c1y,
// c2x, c2y = bezier control points
// duration = how long in milliseconds to do the animation for
// acc      = coefficient of accelleration: 1 = accelerate; 0 = linear; -1 = deccelerate
//            (if acc > 1 then it will go backwards before heading towards destination)
// fn       = execute onSlideEnd() function when animation has finished? true or false.
createObjectById.prototype.bezierSlide = function(x, y, c1x, c1y, c2x, c2y, duration, acc, fn)
{
        clearInterval(this.slideTimer);
        if (!acc) acc = 0;
        if (!fn) fn = false;
        var startTime = new Date().getTime();
        var endTime = startTime + duration;
        this.slideTimer = setInterval('createObjectById.registry[' + this.i + '].slideBezier(' + this.x + ', ' + this.y + ', ' + x + ', ' + y + ', ' + c1x + ', ' + c1y + ', ' + c2x + ', ' + c2y + ', ' + acc + ', ' + startTime + ', ' + endTime + ', ' + fn + ')', 10);
}

createObjectById.prototype.slideBezier = function(startX, startY, endX, endY, c1x, c1y, c2x, c2y, acc, startTime, endTime, fn)
{
        var currentTime = new Date().getTime();
        if (currentTime < endTime)
        {
                var percent = (currentTime - startTime) / (endTime - startTime);
                var startPos = new createObjectById.coord(0, 0);
                var endPos = new createObjectById.coord(1, 1);
                if (acc != 0) var c1 = new createObjectById.coord(0.5 - (acc / 2), 0.5 + (acc / 2)); else c1 = null;
                var pos = createObjectById.getBezier(percent, startPos, endPos, c1);
                var stage = pos.y;
                var c1 = new createObjectById.coord(startX, startY);
                var c2 = new createObjectById.coord(endX, endY);
                var c3 = new createObjectById.coord(c1x, c1y);
                var c4 = new createObjectById.coord(c2x, c2y);
                var pos = createObjectById.getBezier(stage, c1, c2, c3, c4);
                this.moveTo(pos.x, pos.y);
                this.onSlide(pos.x, pos.y);
        }
        else
        {
                clearInterval(this.slideTimer);
                this.moveTo(endX, endY);
                this.onSlide(endX, endY);
                if (fn) this.onSlideEnd(endX, endY);
        }
}

// resizeTo(); resizes a layer from it's current size to another size over a specified time period.
// w, h     = target (width, height) in pixels
// duration = how long in milliseconds to do the animation for
// acc      = coefficient of accelleration: 1 = accelerate; 0 = linear; -1 = deccelerate
//            (if acc > 1 then it will go backwards before heading towards destination)
// fn       = execute onResizeEnd() function when animation has finished? true or false.
createObjectById.prototype.resizeTo = function(w, h, duration, acc, fn)
{
        clearInterval(this.resizeTimer);
        if (!acc) acc = 0;
        if (!fn) fn = false;
        var startTime = new Date().getTime();
        var endTime = startTime + duration;
        this.resizeTimer = setInterval('createObjectById.registry[' + this.i + '].resize(' + this.w + ', ' + this.h + ', ' + w + ', ' + h + ', ' + acc + ', ' + startTime + ', ' + endTime + ', ' + fn + ')', 10);
}

createObjectById.prototype.onResize = new Function();
createObjectById.prototype.onResizeEnd = new Function();

createObjectById.prototype.resize = function(startW, startH, endW, endH, acc, startTime, endTime, fn)
{
        var currentTime = new Date().getTime();
        if (currentTime < endTime)
        {
                var percent = (currentTime - startTime) / (endTime - startTime);
                var c1 = new createObjectById.coord(1, 1);
                var c2 = new createObjectById.coord(0, 0);
                if (acc != 0) var c3 = new createObjectById.coord(0.5 + (acc / 2), 0.5 - (acc / 2)); else c3 = null;
                var pos = createObjectById.getBezier(percent, c1, c2, c3);
                var w = ((endW - startW) * pos.y) + startW;
                var h = ((endH - startH) * pos.y) + startH;
                this.setSize(w, h);
                this.onResize(w, h);
        }
        else
        {
                clearInterval(this.resizeTimer);
                this.setSize(endW, endH);
                this.onResize(endW, endH);
                if (fn) this.onResizeEnd(endW, endH);
        }
}

// fadeTo(); fades a layer from it's current opacity to another opacity over a specified time period.
// o        = target opacity to fade to (between 0 and 100)
// duration = how long in milliseconds to do the animation for
// acc      = coefficient of accelleration: 1 = accelerate; 0 = linear; -1 = deccelerate
//            (if acc > 1 then it will go backwards before heading towards destination)
// fn       = execute onResizeEnd() function when animation has finished? true or false.
createObjectById.prototype.fadeTo = function(o, duration, acc, fn)
{
        clearInterval(this.fadeTimer);
        if (!acc) acc = 0;
        if (!fn) fn = false;
        var startTime = new Date().getTime();
        var endTime = startTime + duration;
        this.fadeTimer = setInterval('createObjectById.registry[' + this.i + '].fade(' + this.o + ', ' + o + ', ' + acc + ', ' + startTime + ', ' + endTime + ', ' + fn + ')', 10);
}

createObjectById.prototype.onFade = new Function();
createObjectById.prototype.onFadeEnd = new Function();

createObjectById.prototype.fade = function(startO, endO, acc, startTime, endTime, fn)
{
        var currentTime = new Date().getTime();
        if (currentTime < endTime)
        {
                var percent = (currentTime - startTime) / (endTime - startTime);
                var c1 = new createObjectById.coord(1, 1);
                var c2 = new createObjectById.coord(0, 0);
                if (acc != 0) var c3 = new createObjectById.coord(0.5 + (acc / 2), 0.5 - (acc / 2)); else c3 = null;
                var pos = createObjectById.getBezier(percent, c1, c2, c3);
                var o = ((endO - startO) * pos.y) + startO;
                this.setOpacity(o);
                this.onFade(o);
        }
        else
        {
                clearInterval(this.fadeTimer);
                this.setOpacity(endO);
                this.onFade(endO);
                if (fn) this.onFadeEnd(endO);
        }
}


// bezier math (calculates a given position along a bezier curve specified by 2, 3 or 4 control points)
createObjectById.b1 = function(t) { return (t * t * t); }
createObjectById.b2 = function(t) { return (3 * t * t * (1 - t)); }
createObjectById.b3 = function(t) { return (3 * t * (1 - t) * (1 - t)); }
createObjectById.b4 = function(t) { return ((1 - t) * (1 - t) * (1 - t)); }

// coordinate constructor
createObjectById.coord = function(x, y)
{
        if (!x) var x = 0;
        if (!y) var y = 0;
        return { x: x, y: y }
}

// finds the coordinates of a point at a certain stage through a bezier curve
createObjectById.getBezier = function(percent, c1, c2, c3, c4)
{
        // if there aren't any extra control points plot a straight line, if there is only 1 make 2nd point same as 1st
        if (!c4 && !c3) var c4 = new createObjectById.coord(c1.x + 3 * (c2.x - c1.x) / 4, c1.y + 3 * (c2.y - c1.y) / 4);
        if (!c4) var c4 = c3;
        if (!c3) var c3 = new createObjectById.coord(c1.x + (c2.x - c1.x) / 4, c1.y + (c2.y - c1.y) / 4);
        var pos = new createObjectById.coord();
        pos.x = c1.x * createObjectById.b1(percent) + c3.x * createObjectById.b2(percent) + c4.x * createObjectById.b3(percent) + c2.x * createObjectById.b4(percent);
        pos.y = c1.y * createObjectById.b1(percent) + c3.y * createObjectById.b2(percent) + c4.y * createObjectById.b3(percent) + c2.y * createObjectById.b4(percent);
        return pos;
}