﻿(function ($) {
    /*----------------------------------------------------------------------------------
    Class: FloatObject
    -------------------------------------------------------------------------------------*/
    function FloatObject(jqObj, params) {
        this.jqObj = jqObj;

        switch (params.speed) {
            case 'fast': this.steps = 5; break;
            case 'normal': this.steps = 10; break;
            case 'slow': this.steps = 20; break;
            default: this.steps = 10;
        };

        var offset = this.jqObj.offset();
        this.currentX = offset.left;
        this.currentY = offset.top;
        this.width = this.jqObj.width();
        this.height = this.jqObj.height();
        this.alwaysVisible = params.alwaysVisible;
        this.alwaysTop = params.alwaysTop;


        this.origX = typeof (params.x) == "string" ? this.currentX : params.x;
        this.origY = typeof (params.y) == "string" ? this.currentY : params.y;


        //now we make sure the object is in absolute positions.
        this.jqObj.css({ 'position': 'absolute', 'top': this.currentY, 'left': this.currentX });
    }

    FloatObject.prototype.updateLocation = function () {
        this.updatedX = $(window).scrollLeft() + this.origX;

        if (this.alwaysTop == false) {
            this.updatedY = $(window).scrollTop() + this.origY;

            if (this.alwaysVisible) {
                if (this.origX + this.width > this.windowWidth())
                    this.updatedX = this.windowWidth() - this.width + $(window).scrollLeft();
                if (this.origY + this.height > this.windowHeight()) {
                    this.updatedY = $(window).scrollTop() + this.windowHeight() - this.height;
                    if (this.updatedY < this.origY) this.updatedY = this.origY;
                }
            }
        }
        else {

            if ($(window).scrollTop() > this.origY) {
                this.updatedY = $(window).scrollTop() + 5;
            }
            else {
                this.updatedY = this.origY + 5;
            }
        }
        this.dx = Math.abs(this.updatedX - this.currentX);
        this.dy = Math.abs(this.updatedY - this.currentY);

        return this.dx || this.dy;
    }

    FloatObject.prototype.windowHeight = function () {
        var de = document.documentElement;

        return self.innerHeight ||
			(de && de.clientHeight) ||
			document.body.clientHeight;
    }

    FloatObject.prototype.windowWidth = function () {
        var de = document.documentElement;

        return self.innerWidth ||
			(de && de.clientWidth) ||
			document.body.clientWidth;
    }


    FloatObject.prototype.move = function () {
        if (this.jqObj.css("position") != "absolute") return;
        var cx = 0;
        var cy = 0;

        if (this.dx > 0) {
            if (this.dx < this.steps / 2)
                cx = (this.dx >= 1) ? 1 : 0;
            else
                cx = Math.round(this.dx / this.steps);

            if (this.currentX < this.updatedX)
                this.currentX += cx;
            else
                this.currentX -= cx;
        }

        if (this.dy > 0) {
            if (this.dy < this.steps / 2)
                cy = (this.dy >= 1) ? 1 : 0;
            else
                cy = Math.round(this.dy / this.steps);

            if (this.currentY < this.updatedY)
                this.currentY += cy;
            else
                this.currentY -= cy;
        }

        this.jqObj.css({ 'left': this.currentX, 'top': this.currentY });
    }



    /*----------------------------------------------------------------------------------
    Object: floatMgr
    -------------------------------------------------------------------------------------*/
    $.floatMgr = {

        FOArray: new Array(),

        timer: null,

        initializeFO: function (jqObj, params) {
            var settings = $.extend({
                x: 0,
                y: 0,
                speed: 'normal',
                alwaysVisible: false,
                alwaysTop: false
            }, params || {});
            var newFO = new FloatObject(jqObj, settings);

            $.floatMgr.FOArray.push(newFO);

            if (!$.floatMgr.timer) $.floatMgr.adjustFO();

            //now making sure we are registered to all required window events
            if (!$.floatMgr.registeredEvents) {
                $(window).bind("resize", $.floatMgr.onChange);
                $(window).bind("scroll", $.floatMgr.onChange);
                $.floatMgr.registeredEvents = true;
            }
        },

        adjustFO: function () {
            $.floatMgr.timer = null;

            var moveFO = false;

            for (var i = 0; i < $.floatMgr.FOArray.length; i++) {
                FO = $.floatMgr.FOArray[i];
                if (FO.updateLocation()) moveFO = true;
            }

            if (moveFO) {
                for (var i = 0; i < $.floatMgr.FOArray.length; i++) {
                    FO = $.floatMgr.FOArray[i];
                    FO.move();
                }

                if (!$.floatMgr.timer) $.floatMgr.timer = setTimeout($.floatMgr.adjustFO, 50);
            }
        },

        stopFloatChk: false,

        onChange: function () {
            if (!$.floatMgr.timer && !$.floatMgr.stopFloatChk) $.floatMgr.adjustFO();
        }
    };

    /*----------------------------------------------------------------------------------
    Function: makeFloat
    -------------------------------------------------------------------------------------*/
    $.fn.makeFloat = function (params) {
        var obj = this.eq(0); //we only operate on the first selected object;
        $.floatMgr.initializeFO(obj, params);
        if ($.floatMgr.timer == null) $.floatMgr.adjustFO();
        return obj;
    };
    $.fn.stopFloat = function (params) {
        $.floatMgr.stopFloatChk = true;
    };

    $.fn.restartFloat = function (params) {
        $.floatMgr.stopFloatChk = false;
    };
})(jQuery);
