//These functions were largely taken from the YUI code and modifyed slightly. YUI
//islicensed under the BSD license. To comply we must include the following:
/*
Software License Agreement (BSD License)

Copyright (c) 2006, Yahoo! Inc.
All rights reserved.

Redistribution and use of this software in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.

* Redistributions in binary form must reproduce the above
  copyright notice, this list of conditions and the
  following disclaimer in the documentation and/or other
  materials provided with the distribution.

* Neither the name of Yahoo! Inc. nor the names of its
  contributors may be used to endorse or promote products
  derived from this software without specific prior
  written permission of Yahoo! Inc.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**
 * Used to determine if the given element is in the DOM.
 * @param el The element to search for.
 */
function inDocument (el)
{
    isAncestor(document.documentElement, el);
}

/**
 * Determines in if a node is a child of a parent.
 * @param haystack The parent node
 * @param needle The child node
 */
function isAncestor (haystack, needle)
{
    if (!haystack || !needle)
    {
        return false;
    }

    if (haystack.contains) {
       return haystack.contains(needle);
    }
    else if ( haystack.compareDocumentPosition ) {
       return !!(haystack.compareDocumentPosition(needle) & 16);
    }
    else { // loop up and test each parent
       var parent = needle.parentNode;

       while (parent) {
          if (parent == haystack) {
             return true;
          }
          else if (parent.tagName.toUpperCase() == 'HTML') {
             return false;
          }

          parent = parent.parentNode;
       }
       return false;
    }
}

/**
 * Given an element within a DOM this method with return an array with two
 * elements that represents the x y position of the element in the page. This
 * method accounts for scrollable elements within the DOM.
 * x = array [0]
 * y = array [1]
 * @param el The element to locate.
 */
function getXY (el)
{
    // has to be part of document to have pageXY
    if (el.offsetParent === null || el.style ['display'] == 'none')
    {
       return false;
    }

    var parentNode = null;
    var pos = [];
    var box;

    if (el.getBoundingClientRect)
    { // IE
       box = el.getBoundingClientRect();
       var doc = document;
       if ( !inDocument(el) && parent.document != document)
       {// might be in a frame, need to get its scroll
            doc = parent.document;
            if (!isAncestor (doc.documentElement, el))
            {
                //I'm really not sure why YUI developers
                //don't get the document reference from the
                //child element instead of doing all this
                //isAncestor stuff. Originally this if block
                //was returning false in the case that uses
                //showModalDialog in IE. So after all the yahoo
                //logic fails above we will resort to this instead.
                doc = el.document;
            }
        }

       var scrollTop = Math.max (
           doc.documentElement.scrollTop, doc.body.scrollTop);
       var scrollLeft = Math.max (
           doc.documentElement.scrollLeft, doc.body.scrollLeft);

       return [box.left + scrollLeft, box.top + scrollTop];
    }
    else
    { //opera, & gecko
       pos = [el.offsetLeft, el.offsetTop];
       parentNode = el.offsetParent;
       if (parentNode != el)
       {
          while (parentNode)
          {
             pos[0] += parentNode.offsetLeft;
             pos[1] += parentNode.offsetTop;
             parentNode = parentNode.offsetParent;
          }
       }
    }

    if (el.parentNode) { parentNode = el.parentNode; }
    else { parentNode = null; }

    //The following code below accounts for block level html elements
    //that may have scrollbars for example a div with a style of
    //overflow:auto

    //Used to accumulate the left scollbar offsets.
    var scrollLeftAccum = 0;
    //Used to accumulate the right scrollbar offsets
    var scrollTopAccum = 0;

    // Walk from the calendar element back up the rest of the body content
    while (parentNode && parentNode.tagName.toUpperCase() != 'BODY' &&
           parentNode.tagName.toUpperCase() != 'HTML')
    {
        // If there is a div.
        if (parentNode.tagName.toUpperCase() == 'DIV')
        {
            // And the div uses the wlp-dialog-inner style. Then we assume we
            // are in the admin tool dialog overlay. In this case we really don't
            // care or want scrollbar offsets so we will reset the accumulator
            // buckets and exit the while loop. Please do not change the class
            // name in toolsDialog.tag or related css files. Hopefully no
            // consumers of this calendar API will use the class name for
            // something other than the admin tools dialog framework
            // functionality.
           if (parentNode.className == 'wlp-dialog-inner')
           {
                scrollLeftAccum = 0;
                scrollTopAccum = 0;
                break;
           }
       }
       //bump the accumulators based on any scrollbar offsets.
       scrollLeftAccum += parentNode.scrollLeft;
       scrollTopAccum += parentNode.scrollTop;

       //This code ends the while loop or gets the next parent node.
       if (parentNode.parentNode) { parentNode = parentNode.parentNode; }
       else { parentNode = null; }
    }

    //No we need to adjust the xy postion that will be returned to account for any
    //scrollbar offsets.
    pos[0] -= scrollLeftAccum;
    pos[1] -= scrollTopAccum;

    return pos;
}
