/* Script by: www.jtricks.com
 * Version: 1.0 (20101208)
 * Latest version:
 * www.jtricks.com/javascript/navigation/floating.html
 */
var floatingMenu =
{
    hasInner: typeof(window.innerWidth) == 'number',
    hasElement: typeof(document.documentElement) == 'object'
        && typeof(document.documentElement.clientWidth) == 'number'
};

var floatingArray =
[
];

floatingMenu.add = function(obj, options)
{
    var name;
    var menu;

    if (typeof(obj) === "string")
        name = obj;
    else
        menu = obj;
        

    if (options == undefined)
    {
        floatingArray.push( 
            {
                id: name,
                menu: menu,

                targetLeft: 0,
                targetTop: 0,

                snap: true
            });
    }
    else
    {
        floatingArray.push( 
            {
                id: name,
                menu: menu,

                targetLeft: options.targetLeft,
                targetRight: options.targetRight,
                targetTop: options.targetTop,
                targetBottom: options.targetBottom,

                centerX: options.centerX,
                centerY: options.centerY,

                snap: options.snap,
                ignoreParentDimensions: options.ignoreParentDimensions
        });
    }
};

floatingMenu.findSingle = function(item)
{
    if (item.id == undefined)
        return;

    item.menu = document.getElementById
        ? document.getElementById(item.id)
        : document.all
          ? document.all[item.id]
          : document.layers[item.id];
};

floatingMenu.move = function (item)
{
    item.menu.style.left = item.nextX + 'px';
    item.menu.style.top = item.nextY + 'px';

    // In order to remove the horizontal scrollbar
    // if the floating div is not shown fully
    // reduce its width
    if (item.right)
    {
        var clientWidth = floatingMenu.hasElement
            ? document.documentElement.clientWidth
            : document.body.clientWidth;

        if (clientWidth - item.nextX < 100)
           item.menu.style.width = (clientWidth - item.nextX) + 'px';
        else
           item.menu.style.width = '100px';
    }
};

floatingMenu.scrollLeft = function()
{
    var w = window;

    // Find top window scroll parameters if we're IFRAMEd
    while (w != w.parent)
        w = w.parent;

    return this.hasInner
        ? w.pageXOffset  
        : this.hasElement  
          ? w.document.documentElement.scrollLeft  
          : w.document.body.scrollLeft;
};

floatingMenu.scrollTop = function()
{
    var w = window;

    // Find top window scroll parameters if we're IFRAMEd
    while (w != w.parent)
        w = w.parent;

    return this.hasInner
        ? w.pageYOffset
        : this.hasElement
          ? w.document.documentElement.scrollTop
          : w.document.body.scrollTop;
};

floatingMenu.windowWidth = function()
{
    return this.hasElement
        ? document.documentElement.clientWidth
        : document.body.clientWidth;
};

floatingMenu.windowHeight = function()
{
    if (floatingMenu.hasElement && floatingMenu.hasInner)
    {
        // Handle Opera 8 problems
        return document.documentElement.clientHeight > window.innerHeight
            ? window.innerHeight
            : document.documentElement.clientHeight
    }
    else
    {
        return floatingMenu.hasElement
            ? document.documentElement.clientHeight
            : document.body.clientHeight;
    }
};

floatingMenu.documentHeight = function()
{
    var innerHeight = this.hasInner
        ? window.innerHeight
        : 0;

    var body = document.body,
        html = document.documentElement;

    return Math.max(
        body.scrollHeight,
        body.offsetHeight, 
        html.clientHeight,
        html.scrollHeight,
        html.offsetHeight,
        innerHeight);
};

floatingMenu.documentWidth = function()
{
    var innerWidth = this.hasInner
        ? window.innerWidth
        : 0;

    var body = document.body,
        html = document.documentElement;

    return Math.max(
        body.scrollWidth,
        body.offsetWidth, 
        html.clientWidth,
        html.scrollWidth,
        html.offsetWidth,
        innerWidth);
};

floatingMenu.calculateCornerX = function(item)
{
    var width = parseInt(item.menu.offsetWidth);

    if (item.centerX)
        return this.scrollLeft() + (this.windowWidth() - width)/2;

    var result;
    if (item.targetLeft == undefined)
        result = this.scrollLeft() + this.windowWidth() - item.targetRight - width;
    else
    {
        result = this.scrollLeft() + item.targetLeft;

        if (result < item.targetLeft)
            result = item.targetLeft;
    }
        
    return result;
};

floatingMenu.calculateCornerY = function(item)
{
    var offsetHeight = parseInt(item.menu.offsetHeight);

    if (item.centerY)
        return this.scrollTop() + (this.windowHeight() - offsetHeight)/2;

    var result;
    if (item.targetTop === undefined)
    {
        result = this.scrollTop()
            + this.windowHeight() 
            - item.targetBottom 
            - offsetHeight
            - item.parentTop;

        if (document.body != item.menu.parentNode
            && result + offsetHeight >= item.parentClientHeight)
            result = item.parentClientHeight - offsetHeight;

        if (result < 0)
            result = 0;
    }
    else
    {
        result = this.scrollTop() + item.targetTop - item.parentTop;

        if (result < item.targetTop)
            result = item.targetTop;
        else if (result + offsetHeight >= item.parentClientHeight)
        {
            result = item.parentClientHeight - offsetHeight;
        }
    }
        
    return result;
};

floatingMenu.computeParent = function(item)
{
    item.parentLeft = 0;  
    item.parentTop = 0;  

    if (item.ignoreParentDimensions)
    {
        item.parentClientHeight = this.documentHeight();
        item.parentClientWidth = this.documentWidth();
        return;
    }

    var obj = item.menu.parentNode;


    item.parentClientHeight = obj.clientHeight;
    item.parentClientWidth = obj.clientWidth;

    // We could have absolutely-positioned DIV wrapped
    // inside relatively-positioned. then parent might not
    // have any height
    if (item.parentClientHeight == 0)
        item.parentClientHeight = obj.offsetParent.clientHeight;

    while (obj.offsetParent)  
    {  
        item.parentLeft += obj.offsetLeft;  
        item.parentTop += obj.offsetTop;  
        obj = obj.offsetParent;
    }  

    if (window == window.parent)
        return;

    // we're IFRAMEd
    var iframes = window.parent.document.body.getElementsByTagName("IFRAME");
    for (var i = 0; i < iframes.length; i++)
    {
        if (iframes[i].contentWindow != window)
           continue;

        obj = iframes[i];
        while (obj.offsetParent)  
        {  
            item.parentLeft += obj.offsetLeft;  
            item.parentTop += obj.offsetTop;  
            obj = obj.offsetParent;
        }  
    }
};


floatingMenu.doFloatSingle = function(item)
{
    this.findSingle(item);

    var stepX, stepY;

    this.computeParent(item);

    var cornerX = this.calculateCornerX(item);

    var stepX = (cornerX - item.nextX) * .07;
    if (Math.abs(stepX) < .5 && item.snap
        || Math.abs(cornerX - item.nextX) == 1)
    {
        stepX = cornerX - item.nextX;
    }

    var cornerY = this.calculateCornerY(item);

    var stepY = (cornerY - item.nextY) * .07;
    if (Math.abs(stepY) < .5 && item.snap
        || Math.abs(cornerY - item.nextY) == 1)
    {
        stepY = cornerY - item.nextY;
    }

    if (Math.abs(stepX) > 0 ||
        Math.abs(stepY) > 0)
    {
        item.nextX += stepX;
        item.nextY += stepY;
        this.move(item);
    }
};

floatingMenu.fixTargets = function()
{
};

floatingMenu.fixTarget = function(item)
{
};

floatingMenu.doFloat = function()
{
    this.fixTargets();
    for (var i=0; i < floatingArray.length; i++)
    {
        this.fixTarget(floatingArray[i]);
        this.doFloatSingle(floatingArray[i]);
    }
    setTimeout('floatingMenu.doFloat()', 0);
};

floatingMenu.insertEvent = function(element, listener, handler)
{
    var oldHandler = element[listener];
    element[listener] = function (e)
        {
            e = (e) ? e : window.event;
            var result = handler(e);
            return (oldHandler != undefined) 
                && (oldHandler(e) == true)
                && (result == true);
        };
};

floatingMenu.init = function()
{
    floatingMenu.fixTargets();

    for (var i=0; i < floatingArray.length; i++)
    {
        floatingMenu.initSingleMenu(floatingArray[i]);
    }

    setTimeout('floatingMenu.doFloat()', 100);
};

// Some browsers init scrollbars only after
// full document load.
floatingMenu.initSingleMenu = function(item)
{
    this.findSingle(item);
    this.computeParent(item);
    this.fixTarget(item);
    item.nextX = this.calculateCornerX(item);
    item.nextY = this.calculateCornerY(item);
    this.move(item);
};

floatingMenu.insertEvent(window, 'onload', floatingMenu.init);

