﻿/* Script by: www.jtricks.com
* Version: 20071017
* Latest version:
* www.jtricks.com/javascript/navigation/floating.html
* Modified by Blaise Braye
*/


function FloatingMenu(menu) {
    this.menu = menu;

    this.targetX = 'center';
    this.targetY = 2;

    this.hasInner = typeof (window.innerWidth) == 'number';
    this.hasElement = typeof (document.documentElement) == 'object'
        && typeof (document.documentElement.clientWidth) == 'number';

    if (document.layers)
        this.AddEvent(window, 'onload', this.CreateDelegate("Init"));
    else {
        this.Init();
        this.AddEvent(window, 'onload', this.CreateDelegate("InitSecondary"));
    }

};

// AddEvent designed by Aaron Moore
FloatingMenu.prototype.AddEvent = function(element, listener, handler) {
    if (typeof element[listener] != 'function' ||
       typeof element[listener + '_num'] == 'undefined') {
        element[listener + '_num'] = 0;
        if (typeof element[listener] == 'function') {
            element[listener + 0] = element[listener];
            element[listener + '_num']++;
        }
        element[listener] = function(e) {
            var r = true;
            e = (e) ? e : window.event;
            for (var i = element[listener + '_num'] - 1; i >= 0; i--) {
                if (element[listener + i](e) == false)
                    r = false;
            }
            return r;
        }
    }

    //if handler is not already stored, assign it
    for (var i = 0; i < element[listener + '_num']; i++)
        if (element[listener + i] == handler)
        return;
    element[listener + element[listener + '_num']] = handler;
    element[listener + '_num']++;
};

FloatingMenu.prototype.CreateDelegate = function(methodName) {
    obj = this;

    return function() {
        return obj[methodName].apply(obj, arguments);
    };
};





FloatingMenu.prototype.Move = function() {
    this.menu.style.left = this.nextX + 'px';
    this.menu.style.top = this.nextY + 'px';
};

FloatingMenu.prototype.ComputeShifts = function() {
    var de = document.documentElement;

    this.shiftX =
        this.hasInner
        ? pageXOffset
        : this.hasElement
          ? de.scrollLeft
          : document.body.scrollLeft;
    if (this.targetX < 0) {
        this.shiftX +=
            this.hasElement
            ? de.clientWidth
            : document.body.clientWidth;
    }

    this.shiftY =
        this.hasInner
        ? pageYOffset
        : this.hasElement
          ? de.scrollTop
          : document.body.scrollTop;
    if (this.targetY < 0) {
        if (this.hasElement && this.hasInner) {
            // Handle Opera 8 problems
            this.shiftY +=
                de.clientHeight > window.innerHeight
                ? window.innerHeight
                : de.clientHeight
        }
        else {
            this.shiftY +=
                this.hasElement
                ? de.clientHeight
                : document.body.clientHeight;
        }
    }
};

FloatingMenu.prototype.CalculateCornerX = function() {
    if (this.targetX != 'center')
        return this.shiftX + this.targetX;

    var width = parseInt(this.menu.offsetWidth);

    var cornerX =
        this.hasElement
        ? (this.hasInner
           ? pageXOffset
           : document.documentElement.scrollLeft) +
          (document.documentElement.clientWidth - width) / 2
        : document.body.scrollLeft +
          (document.body.clientWidth - width) / 2;
    return cornerX;
};

FloatingMenu.prototype.CalculateCornerY = function() {
    if (this.targetY != 'center')
        return this.shiftY + this.targetY;

    var height = parseInt(this.menu.offsetHeight);

    // Handle Opera 8 problems
    var clientHeight =
        this.hasElement && this.hasInner
        && document.documentElement.clientHeight
            > window.innerHeight
        ? window.innerHeight
        : document.documentElement.clientHeight

    var cornerY =
        this.hasElement
        ? (this.hasInner
           ? pageYOffset
           : document.documentElement.scrollTop) +
          (clientHeight - height) / 2
        : document.body.scrollTop +
          (document.body.clientHeight - height) / 2;
    return cornerY;
};

FloatingMenu.prototype.DoFloat = function() {
    var stepX, stepY;

    this.ComputeShifts();

    var cornerX = this.CalculateCornerX();

    var stepX = (cornerX - this.nextX) * .09;
    if (Math.abs(stepX) < .1) {
        stepX = cornerX - this.nextX;
    }

    var cornerY = this.CalculateCornerY();

    var stepY = (cornerY - this.nextY) * .09;
    if (Math.abs(stepY) < .1) {
        stepY = cornerY - this.nextY;
    }

    if (Math.abs(stepX) > 0 ||
        Math.abs(stepY) > 0) {
        this.nextX += stepX;
        this.nextY += stepY;
        this.Move();
    }

    setTimeout(this.CreateDelegate('DoFloat'), 20);
};


FloatingMenu.prototype.Init = function() {
    this.InitSecondary();
    this.DoFloat();
};

// Some browsers Init scrollbars only after
// full document load.
FloatingMenu.prototype.InitSecondary = function() {
    this.ComputeShifts();
    this.nextX = this.CalculateCornerX();
    this.nextY = this.CalculateCornerY();
    this.Move();
}
