//****************************************************************************
// Copyright (c) 2005, Coveo Solutions Inc.
//****************************************************************************

//****************************************************************************
/// <summary>
/// Retrieves the absolute position of an HTML object (in pixels).
/// </summary>
/// <param name="p_Object">The object whose position to retrieve.</param>
/// <returns>An object that contains the information.</returns>
//****************************************************************************
function CNL_GetPosition(p_Object)
{
    var pos = new Object();
    pos.m_Left = 0;
    pos.m_Top = 0;
    var obj = p_Object;
    while (obj.offsetParent) {
        pos.m_Left += obj.offsetLeft;
        pos.m_Top += obj.offsetTop;
        obj = obj.offsetParent;
    }
  
    return pos;
}

//****************************************************************************
/// <summary>
/// Retrieves the size of an HTML object (in pixels).
/// </summary>
/// <param name="p_Object">The object whose size to retrieve.</param>
/// <returns>An object that contains the information.</returns>
//****************************************************************************
function CNL_GetSize(p_Object)
{
    var size = new Object();
    size.m_Width = p_Object.offsetWidth;
    size.m_Height = p_Object.offsetHeight;
  
    return size;
}

//****************************************************************************
/// <summary>
/// Retrieves the bounding rectangle of an HTML object (in pixels).
/// </summary>
/// <param name="p_Object">The object whose bounding rectangle to retrieve.</param>
/// <returns>An object that contains the information.</returns>
//****************************************************************************
function CNL_GetBoundingRectangle(p_Object)
{
    var pos = CNL_GetPosition(p_Object);
    var size = CNL_GetSize(p_Object);
    var rect = new Object();
    rect.m_Left = pos.m_Left;
    rect.m_Top = pos.m_Top;
    rect.m_Right = pos.m_Left + size.m_Width;
    rect.m_Bottom = pos.m_Top + size.m_Height;
  
    return rect;
}

//****************************************************************************
/// <summary>
/// Retrieves the bounding of the region that is visible in the window (in pixels).
/// </summary>
/// <returns>An object that contains the information.</returns>
//****************************************************************************
function CNL_GetVisibleRectangle()
{
    var rect = new Object();
    rect.m_Left = document.body.scrollLeft;
    rect.m_Top = document.body.scrollTop;
    rect.m_Right = rect.m_Left + document.body.clientWidth;
    rect.m_Bottom = rect.m_Top + document.body.clientHeight;
  
    return rect;
}

//****************************************************************************
/// <summary>
/// Checks if two rectangles overlap.
/// </summary>
/// <returns>Whether the two rectangles overlap.</returns>
//****************************************************************************
function CNL_IsOverlap(p_Rect1, p_Rect2)
{
    // Look for an horizontal overlap
    var horiz = (p_Rect1.m_Left >= p_Rect2.m_Left &&
                 p_Rect1.m_Left < p_Rect2.m_Right) ||
                (p_Rect1.m_Right > p_Rect2.m_Left &&
                 p_Rect1.m_Right < p_Rect2.m_Right) ||
                (p_Rect2.m_Left >= p_Rect1.m_Left &&
                 p_Rect2.m_Left < p_Rect1.m_Right) ||
                (p_Rect2.m_Right > p_Rect1.m_Left &&
                 p_Rect2.m_Right < p_Rect1.m_Right);

    // Look for a vertical overlap
    var vert = (p_Rect1.m_Top >= p_Rect2.m_Top &&
                p_Rect1.m_Top < p_Rect2.m_Bottom) ||
               (p_Rect1.m_Bottom > p_Rect2.m_Top &&
                p_Rect1.m_Bottom < p_Rect2.m_Bottom) ||
               (p_Rect2.m_Top >= p_Rect1.m_Top &&
                p_Rect2.m_Top < p_Rect1.m_Bottom) ||
               (p_Rect2.m_Bottom > p_Rect1.m_Top &&
                p_Rect2.m_Bottom < p_Rect1.m_Bottom);

    return horiz && vert;
}

//****************************************************************************
/// <summary>
/// Positions an object relative to another.
/// </summary>
/// <param name="p_Object">The object to position.</param>
/// <param name="p_Reference">The object to position relatively to.</param>
/// <param name="p_Position">Where to place the object from the other.</param>
//****************************************************************************
function CNL_PositionObject(p_Object, p_Reference, p_Position)
{
    var left;
    var top;
    var osize = CNL_GetSize(p_Object);
    var rrect = CNL_GetBoundingRectangle(p_Reference);
    if (p_Position == 'LeftAbove') {
        left = rrect.m_Left - osize.m_Width;
        top = rrect.m_Bottom - osize.m_Height;
    } else if (p_Position == 'RightAbove') {
        left = rrect.m_Right;
        top = rrect.m_Bottom - osize.m_Height;
    } else if (p_Position == 'LeftBelow') {
        left = rrect.m_Left - osize.m_Width;
        top = rrect.m_Top;
    } else if (p_Position == 'RightBelow') {
        left = rrect.m_Right;
        top = rrect.m_Top;
    } else if (p_Position == 'AboveLeft') {
        left = rrect.m_Left;
        top = rrect.m_Top - osize.m_Height;
    } else if (p_Position == 'AboveRight') {
        left = rrect.m_Right - osize.m_Width;
        top = rrect.m_Top - osize.m_Height;
    } else if (p_Position == 'BelowLeft') {
        left = rrect.m_Left;
        top = rrect.m_Bottom;
    } else if (p_Position == 'BelowRight') {
        left = rrect.m_Right - osize.m_Width;
        top = rrect.m_Bottom;
    }

    p_Object.style.left = left + 'px';
    p_Object.style.top = top + 'px';
}

//****************************************************************************
/// <summary>
/// Rectifies the position of an object so that it isn't out of the screen.
/// </summary>
/// <param name="p_Object">The object whose position to rectify.</param>
/// <param name="p_Reference">The object to position relatively to.</param>
//****************************************************************************
function CNL_RectifyPosition(p_Object, p_Reference)
{
    var osize = CNL_GetSize(p_Object);
    var orect = CNL_GetBoundingRectangle(p_Object);
    var rrect = CNL_GetBoundingRectangle(p_Reference);
    var vrect = CNL_GetVisibleRectangle();

    // Rectify position if needed. We perform a first pass trying to avoid
    // putting the object over the reference.
    if (orect.m_Top < vrect.m_Top) {
        orect.m_Top = vrect.m_Top;
        orect.m_Bottom = orect.m_Top + osize.m_Height;
        if (CNL_IsOverlap(orect, rrect)) {
            orect.m_Top = rrect.m_Bottom;
            orect.m_Bottom = orect.m_Top + osize.m_Height;
        }
    }
    if (orect.m_Bottom > vrect.m_Bottom) {
        orect.m_Top = vrect.m_Bottom - osize.m_Height;
        orect.m_Bottom = orect.m_Top + osize.m_Height;
        if (CNL_IsOverlap(orect, rrect)) {
            orect.m_Top = rrect.m_Top - osize.m_Height;
            orect.m_Bottom = orect.m_Top + osize.m_Height;
        }
    }
    if (orect.m_Left < vrect.m_Left) {
        orect.m_Left = vrect.m_Left;
        orect.m_Right = vrect.m_Left + osize.m_Width;
        if (CNL_IsOverlap(orect, rrect)) {
            orect.m_Left = rrect.m_Right;
            orect.m_Right = orect.m_Left + osize.m_Width;
        }
    }
    if (orect.m_Right > vrect.m_Right) {
        orect.m_Left = vrect.m_Right - osize.m_Width;
        orect.m_Right = orect.m_Left + osize.m_Width;
        if (CNL_IsOverlap(orect, rrect)) {
            orect.m_Left = vrect.m_Left;
            orect.m_Right = vrect.m_Left + osize.m_Width;
        }
    }

    // We then perform a second pass to ensure the object is always within
    // the visible space, and without caring about getting over the reference.
    if (orect.m_Top < vrect.m_Top) {
        orect.m_Top = vrect.m_Top;
        orect.m_Bottom = orect.m_Top + osize.m_Height;
    }
    if (orect.m_Bottom > vrect.m_Bottom) {
        orect.m_Top = vrect.m_Bottom - osize.m_Height;
        orect.m_Bottom = orect.m_Top + osize.m_Height;
    }
    if (orect.m_Left < vrect.m_Left) {
        orect.m_Left = vrect.m_Left;
        orect.m_Right = vrect.m_Left + osize.m_Width;
    }
    if (orect.m_Right > vrect.m_Right) {
        orect.m_Left = vrect.m_Right - osize.m_Width;
        orect.m_Right = orect.m_Left + osize.m_Width;
    }

    p_Object.style.left = orect.m_Left + 'px';
    p_Object.style.top = orect.m_Top + 'px';
}

